在异步编程中,许多操作都会放在回调函数(callback)中,每增加一个异步请求,就会多添加一层回调函数的嵌套,多个异步操作就形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改,过多的回调也就会导致陷入“回调地狱”。
它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。
resolve
和reject
参数的函数;在状态由pending
变为fulfilled
时,从resolve中将value传出;
在状态由pending
变为rejected
时,将error抛出
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。promise.then(function(value) {
// success
}, function(error) {
// failure
});
then
方法加载回调函数,catch
方法捕捉执行过程中抛出的错误。或者这样捕获error:
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
finally
方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.all
| Promise.race
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
特征:1.function
关键字与函数名之间有一个星号;2.函数体内部使用yield
表达式,定义不同的内部状态
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
调用遍历器对象的next
方法,使得指针移向下一个状态。
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
for...of
循环可以自动遍历 Generator 函数时生成的Iterator
对象,且此时不再需要调用next
方法。
function* foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
}
for (let v of foo()) {
console.log(v);
}
在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。
// 正常版本的readFile(多参数版本)
fs.readFile(fileName, callback);
// Thunk版本的readFile(单参数版本)
var Thunk = function (fileName) {
return function (callback) {
return fs.readFile(fileName, callback);
};
};
var readFileThunk = Thunk(fileName);
readFileThunk(callback);
Thunk函数实现上是针对多参数的currying(柯里化),来实现对函数的惰性求值。
任何函数,只要参数有回调函数,就能写成Thunk函数的形式。
var readFileThunk = fs.readFile.bind(null, './oranges.txt', 'utf8');
readFileThunk(someCallback);
async 函数其实就是 Generator 函数的语法糖
await
后一般是一个Promise
对象。
async
函数返回一个 Promise
对象时,就可以使用then
方法添加回调函数。
当函数执行的时候,一旦遇到await
就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};