// 堆代码 duidaima.com getUser(function(user, err) { if (err) { console.log(err); return; } console.log(user); });但是这种处理异步操作的方式有一个明显的缺点,就是代码嵌套太深,导致可读性非常差。而 Promise 可以简单而优雅的解决这个问题。我们可以简单地使用 Promise 来封装异步操作:
getUser() .then(function(user) { console.log(user); }) .catch(function(err) { console.log(err); }); function getUser() { return new Promise(function(resolve, reject) { // 异步操作 if (success) { resolve(user); } else { reject(err); } }); }上述代码相比于回调函数要清晰简单很多。如果出错,也可以通过 catch 捕捉到错误。
Promise.all([getUser1(), getUser2(), getUser3()]) .then(function(results) { console.log(results); }); function getUser1() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(1); }, 500); }); } function getUser2() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(2); }, 500); }); } function getUser3() { return new Promise(function(resolve, reject) { setTimeout(function() { reject(3); }, 500); }); }在上述代码中,getUser1、getUser2、getUser3 都是异步函数,分别在 500 毫秒后分别正常返回了数字 1、2 和返回错误 3.而在 Promise.all 的 then 函数中,我们得到了一个包含 1、2 的数组,同时用户的错误也被 catch 到了。
与 Promise.all 不同,Promise.allSettled 方法会等待所有 Promise 实例都返回对应的状态(不论是 resolved 还是 rejected),只有所有实例的状态都被转化为 settled 后,Promise.allSettled 才会执行。
例如,在下面这个例子中,getUser1、getUser2、getUser3 都返回了正确的值,但是在 getUser4 中出错了,Promise.allSettled 依然会异步等待所有的返回,最终返回状态集合。
Promise.allSettled([getUser1(), getUser2(), getUser3(), getUser4()]) .then(function(results) { console.log(results); }); function getUser1() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(1); }, 500); }); } function getUser2() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(2); }, 500); }); } function getUser3() { return new Promise(function(resolve, reject) { setTimeout(function() { reject(3); }, 500); }); } function getUser4() { return new Promise(function(resolve, reject) { setTimeout(function() { reject(4); }, 500); }); }在这个例子中,我们使用了 getUser4 函数,并在其中引发了错误。但是,Promise.allSettled 还是会异步等待结果并返回一个结果状态的集合。结果中每个对象都有一个 status 属性,该属性是 settled、fulfilled、rejected 中的一个。
[ { "status": "fulfilled", "value": 1 }, { "status": "fulfilled", "value": 2 }, { "status": "rejected", "reason": 3 }, { "status": "rejected", "reason": 4 } ]可以看到,每个 Promise 实例的状态都被等待到之后才执行,而且其中的 fulfilled 或者 reject 状态也以对象形式被统一返回了。
var promise1 = Promise.resolve(3); var promise2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'foo'); }); Promise.allSettled([promise1, promise2]) .then(function(results) { console.log(results); });这个代码在前两个 Promise 实例中是已知的。可以看到,我们使用 Promise.resolve 和 Promise 构造函数来创建返回数字 3 和字符串 'foo' 的 Promise 实例,而结果数组始终都是相同的:
[ { "status": "fulfilled", "value": 3 }, { "status": "fulfilled", "value": "foo" } ]
Promise.all([getUser1(), getUser2(), getUser3()]) .then(function(results) { console.log(results); }) .catch(function(err) { console.log(err); }); Promise.allSettled([getUser1(), getUser2(), getUser3()]) .then(function(results) { console.log(results); }); function getUser1() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(1); }, 500); }); } function getUser2() { return new Promise(function(resolve, reject) { setTimeout(function() { resolve(2); }, 500); }); } function getUser3() { return new Promise(function(resolve, reject) { setTimeout(function() { reject(new Error('error')); }, 500); }); }这是包含 catch 函数的 Promise.all 和包含 then 函数的 Promise.allSettled 的输出结果:
[ { "status": "rejected", "reason": Error: error at ... }, undefined, undefined ]结果 2:
[ { "status": "fulfilled", "value": 1 }, { "status": "fulfilled", "value": 2 }, { "status": "rejected", "reason": Error: error at ... } ]在这个例子中,我们使用了 getUser3 函数并引发了错误。但是,在使用 Promise.all 时,我们只会得到一个错误,而使用 Promise.allSettled 时我们会得到三种不同的状态值集合。