一、回调模式
早期对于异步操作的处理主要是通过回调函数的方式进行,将函数传入异步操作,当该操作完成后该函数将会被调用,这里会存在一个问题,当嵌套多个回调函数的时候,会陷入回调地狱,代码的可读性变得极差。
method1(function(err, result) {
if (err) {
throw err;
}
method2(function(err, result) {
if (err) {
throw err;
}
method3(function(err, result) {
if (err) {
throw err;
}
method4(function(err, result) {
if (err) {
throw err;
}
method5(result);
});
});
});
});
二、Promise
Promise代表一个承诺,表示将来在某时刻完成。Promise是ECMAscript 6提供的一个异步编程的API,可以通过它来传递异步消息。
2.1 Promise生命周期
当进行异步操作并且尚未完成时,Promise状态位挂起态(Pedding),当操作完成时,Promise会根据操作的结果转为一下两种状态:
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败
2.2 基本使用
使用new创建Promise,该类接收一个函数,该函数的两个参数分别是resolve和reject,其中在异步操作成功完成的时候使用resolve函数传递成功参数,在异步操作异常的时候使用reject函数传递失败参数。
// 创建Promise
const promise = new Promise(function(resolve, reject) {
// 耗时操作
setTimeout(() => {
resolve("success done");
}, 2000);
});
// 接收处理结果
promise.then(function(content) {
// 完成
}, function(err) {
// 拒绝
});
promise.then(content => {
// 完成
});
promise.then(null, function(content) {
// 拒绝
});
// 等同于
promise.catch(function(err) {
// 拒绝
});
如果在Promise内部抛出异常,Promise的拒绝函数将会执行。
let promise = new Promise(function(resolve, reject) {
throw new Error("Explosion!");
});
promise.catch(function(error) {
console.log(error.message); // "Explosion!"
});
2.3 链式调用
对then或catch的调用,实际上是返回了另一个Promise,当前Promise完成或拒绝后,下一个Promise才会执行。处理函数的返回值将会传递给下个处理函数,拒绝函数也是同样。
let p1 = new Promise(function(resolve, reject) {
resolve(41);
});
p1.then(function(value) {
console.log(value); // 41
}).then(function() {
console.log("finish"); // finish
});
p1.then(function(value) {
return value + 1;
}).then(function(value) {
console.log(value); // 42
});
Promise.all()
Promise接收多个Promise作为参数,仅当所有Promise都完成时,所返回的Promise才算完成。
let p1 = new Promise(function(resolve, reject) {
resolve(42);
});
let p2 = new Promise(function(resolve, reject) {
resolve(43);
});
let p3 = new Promise(function(resolve, reject) {
resolve(44);
});
let p4 = Promise.all([p1, p2, p3]);
p4.then(function(value) {
console.log(Array.isArray(value)); // true
console.log(value[0]); // 42
console.log(value[1]); // 43
console.log(value[2]); // 44
});
当任一Promise被拒绝时,那么所返回的Promise会被立刻拒绝,而不会等待其他的Promise。
let p1 = new Promise(function(resolve, reject) {
resolve(42);
});
let p2 = new Promise(function(resolve, reject) {
reject(43);
});
let p3 = new Promise(function(resolve, reject) {
resolve(44);
});
let p4 = Promise.all([p1, p2, p3]);
p4.catch(function(value) {
console.log(Array.isArray(value)); // false
console.log(value); // 43
});
Promise.race()
Promise.race类似Promise.all,不同的是任意有个Promise被解决或被拒绝,Promise.race就会返回该Promise。
let p1 = Promise.resolve(42);
let p2 = new Promise(function(resolve, reject) {
resolve(43);
});
let p3 = new Promise(function(resolve, reject) {
resolve(44);
});
let p4 = Promise.race([p1, p2, p3]);
p4.then(function(value) {
console.log(value); // 42
});