fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
用同步代码写异步流程function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next() // { value: 'hello', done: false }
hw.next() // { value: 'world', done: false }
hw.next() // { value: 'ending', done: true }
hw.next() // { value: undefined, done: true }
function* f() {
console.log('执行了!')
}
var generator = f();
setTimeout(function () {
generator.next()
}, 2000);
在 Generator 函数内部调用另一个 Generator 函数是没有效果的。
function* foo() {
}
function* bar() {
yield 'x';
foo();
yield 'y';
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
Generator函数也有prototype属性,同样可以继承原型方法。
function* g() {
}
g.prototype.hello = function () {
return 'hi!';
};
let obj = g();
obj instanceof g // true
obj.hello() // hi!
function* g() {
this.a = 11;
}
let obj = g();
obj.a // undefined
利用Generator函数和yield语句可以代替异步回调
function* loadUI() {
showLoadingScreen();
yield loadUIDataAsynchronously();
hideLoadingScreen();
}
var loader = loadUI();
loader.next(); // 加载UI
loader.next(); // 卸载UI
function* numbers() {
let file = new FileReader("numbers.txt");
try {
while(!file.eof) {
yield parseInt(file.readLine(), 10);
}
} finally {
file.close();
}
}
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
function* longRunningTask(value1) {
try {
var value2 = yield step1(value1);
var value3 = yield step2(value2);
var value4 = yield step3(value3);
var value5 = yield step4(value4);
// Do something with value4
} catch (e) {
// Handle any error from step1 through step4
}
}
ES6规定,Promise对象是一个构造函数,用来生成Promise实例
var promise = new Promise(function(resolve, reject) {
// ... some code
if (1){
resolve('aaa');
} else {
reject(error);
}
});
console.log(promise)
// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "aaa"}
Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
var promise = new Promise(function(resolve, reject) {resolve('aaa')});
promise.then(function(value) {
// success
console.log(value); // 输出 aaa, 如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数
}, function(error) {
// failure
});
异步加载图片
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
// 加载成功
image.onload = function() {
resolve(image);
};
// 加载失败
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
// 将jQuery生成的deferred对象,转为一个新的Promise对象
var jsPromise = Promise.resolve($.ajax('/whatever.json'));
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
var p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
var p = Promise.resolve();
p.then(function () {
// ...
});
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected
var p = Promise.reject('出错了');
// 等同于
var p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
var promise = new Promise(
function(resolve, reject) {
throw new Error('test');
// 或者 reject(new Error('test'));
});
promise.catch(function(error) {
console.log(error);
});
// Error: test
// p1、p2、p3都是 Promise 实例
var p = Promise.all([p1, p2, p3]);
1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled
2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected
例子
// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
// p1、p2、p3都是 Promise 实例
var p = Promise.all([p1, p2, p3]);
Generator 函数版本
var fs = require('fs');
var readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) reject(error);
resolve(data);
});
});
};
var gen = function* () {
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
var fs = require('fs');
var readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) reject(error);
resolve(data);
});
});
};
var asyncReadFile = async function () {
var f1 = await readFile('/etc/fstab');
var f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
async getAvatar(name) {
const cache = await cachePromise(name);
return cache;
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};
async函数返回一个 Promise 对象,async函数内部return语句返回的值,会成为then方法回调函数的参数
async function f() {
return 'hello world';
}
f().then(v => console.log(v))
// "hello world"
async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态
async function f() {
throw new Error('出错了');
}
f().then(
v => console.log(v),
e => console.log(e)
)
async function getTitle(url) {
let response = await fetch(url); // 抓取网页
let html = await response.text(); // 取出文本
return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"
await命令后面是一个 Promise 对象,如果不是,会被转成一个立即resolve的 Promise 对象
async function f() {
return await 123;
}
f().then(v => console.log(v))
// 123
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world'); // 会执行
}
f().then(v => console.log(v))
// hello world
async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。
async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () { // spawn函数就是自动执行器
// ...
});
}
function spawn(genF) {
return new Promise(function(resolve, reject) {
var gen = genF();
function step(nextF) {
try {
var next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); }); // 递归自动执行next
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
ES6引入了 Class(类)这个概念,通过class关键字,可以定义类
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var p = new Point(2,3);
p.toString();
class Point {
constructor() {}
toString() {}
toValue() {}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
class Point {
constructor(){}
}
Object.assign(Point.prototype, {
toString(){},
toValue(){}
});
Point.prototype.constructor === Point // true
undefined
undefined
undefined