# Promise 方法
Promise
中的执行函数是同步进行的,但是里面存在着异步操作,在异步操作结束后会调用 resolve
方法,或者中途遇到错误调用 reject
方法,这两者都是作为微任务进入到 EventLoop
中。
下面的例子,来了解同步和异步
console.log(1)
let promiseDemo = new Promise((resolve, reject) => {
console.log(2)
let random = Math.random()
if (random >= 0.2) {
resolve('success')
console.log(3)
} else {
reject('failed')
console.log(3)
}
})
console.log(8)
async function test() {
console.log(4)
let result = await promiseDemo
return result
}
setTimeout(() => {
console.log(7)
}, 0)
test().then(result => {
console.log(5)
}).catch((result) => {
console.log(5)
})
console.log(6)
// 1 2 3 8 4 6 7 5
# then()
用于成功时的回调函数。
# catch()
用于指定发生错误时的回调函数。
一般来说,不要在then()
方法里面定义 Reject
状态的回调函数(即then
的第二个参数),总是使用catch
方法。
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good
promise
.then(function(data) {
// success
})
.catch(function(err) {
// error
});
# finally()
finally()
方法用于指定不管Promise
对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
finally
方法的回调函数不接受任何参数,方法里面的操作,是与状态无关的,不依赖于Promise
的执行结果。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
promise
.finally(() => {
// 语句
});
// 等同于
promise
.then(
result => {
// 语句
return result;
},
error => {
// 语句
throw error;
}
);
上面代码中,如果不使用finally
方法,同样的语句需要为成功和失败两种情况各写一次。有了finally
方法,则只需要写一次。
# all()
方法用于将多个 Promise
实例,包装成一个新的 Promise
实例。
只有Promise1
、Promise2
、Promise3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时Promise1
、Promise2
、Promise3
的返回值组成一个数组,传递给p
的回调函数。
只要Promise1
、Promise2
、Promise3
之中有一个被rejected
,p的状态才会变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。
let Promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num <= 5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000)
})
let Promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num <= 5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000)
})
let Promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num <= 5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000)
})
let p = Promise.all([Promise1, Promise2, Promise3])
p.then((res) => {
// 三个都成功则成功
console.log('resolved', res)
}).catch((err) => {
// 只要有失败,则失败
console.log('rejectd', err)
})
适合使用的场景,在所有异步方法都执行完毕后,再执行某一方法。
# race()
接收数组,方法返回一个promise
,一旦迭代器中的某个promise
解决或拒绝,返回的promise
就会解决或拒绝。
race就是竞争的意思,数组内的Promise实例,谁执行的快,就返回谁的执行结果,不管是成功还是失败
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, "one");
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, "two");
});
Promise.race([p1, p2]).then(function(value) {
console.log(value); // "two"
// 两个都完成,但 p2 更快
});
var p3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, "three");
});
var p4 = new Promise(function(resolve, reject) {
setTimeout(reject, 500, "four");
});
Promise.race([p3, p4]).then(function(value) {
// p3 更快,所以它完成了
console.log(value); // "three"
}, function(reason) {
// 未被调用
});
var p5 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, "five");
});
var p6 = new Promise(function(resolve, reject) {
setTimeout(reject, 100, "six");
});
Promise.race([p5, p6]).then(function(value) {
// 未被调用
}, function(reason) {
console.log(reason); // "six" p6 更快,所以它失败了
});
# allSettled()
接受一组 Promise
实例作为参数,包装成一个新的Promise
实例。只有等到所有这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束。该方法由 ES2020 引入。
该方法返回的新的Promise
实例,一旦结束,状态总是fulfilled
,不会变成rejected
。
状态变成fulfilled
后,Promise
的监听函数接收到的参数是一个数组,每个成员对应一个传入Promise.allSettled()
的Promise
实例。
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([resolved, rejected]);
allSettledPromise.then((results) => {
console.log(results);
});
// [{status: "fulfilled", value: 42}, {status: "rejected", reason: -1}]
# 参考
← Ajax Promise 回调 →