Promise
是一个对象,它代表了一个异步操作的最终完成或者失败。
本质上,Promise 是一个被某些函数传出的对象,我们附加回调函数(callback)使用它,而不是将回调函数传入那些函数内部。
function wait(ms) { //执行函数返回一个Promise对象
return new Promise((resolve, reject) => { //成功的回调函数及失败的回调函数
setTimeout(() => {
console.log('异步函数执行完成');
resolve(ms) // 在异步函数完成后再调用resolve()
}, ms);
})
}
console.log('计时开始');
wait(1000).then((ms) => { //then()的第一个参数为成功的回调函数resolve()
console.log(`异步执行时间为${ms}毫秒`); // 将ms参数传入回调函数,使用字符串模板打印
})
// 计时开始
// 异步函数执行完成
// 异步执行时间为1000ms
约定
不同于“老式”的传入回调,在使用 Promise 时,会有以下约定:
- 在 本轮 Javascript event loop(事件循环)运行完成 之前,回调函数是不会被调用的。
- 通过 then() 添加的回调函数总会被调用,即便它是在异步操作完成之后才被添加的函数。
- 通过多次调用 then(),可以添加多个回调函数,它们会按照插入顺序一个接一个独立执行。
因此,Promise 最直接的好处就是链式调用(chaining)。
function wait(ms) { //执行函数返回一个Promise对象
return new Promise((resolve, reject) => { //成功的回调函数及失败的回调函数
setTimeout(() => {
console.log('异步函数执行完成');
resolve(ms) // 在异步函数完成后再调用resolve()
}, ms);
})
}
console.log('计时开始');
setTimeout(() => {
console.log('计时3秒'); //3秒后输出
wait(3000).then((ms) => {
console.log(`Promise异步执行时间为${ms}毫秒`); //6秒后输出
})
}, 3000);
- 以上代码演示了,通过 then() 添加的回调函数总会被调用,即便它是在异步操作完成之后才被添加的函数。
链式调用
在执行then()中的回调函数时返回一个新的Promise对象,可以继续使用then()对这个对象进行调用,形成一个 Promise 链
function wait(ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(ms)
}, ms);
})
}
wait(1000)
.then((ms)=> { //ms = 1000
console.log(`等待了${ms}毫秒`);
return wait(ms)
})
.then((ms)=> { //ms = 1000
console.log(`等待了${ms}毫秒`);
return wait(2000)
})
.then((ms)=> { //ms = 2000
console.log(`等待了${ms}毫秒`);
return wait(ms)
})
.then((ms)=> { //ms = 2000
console.log(`等待了${ms}毫秒`);
})
.then((ms)=> { //找不到ms变量
console.log(`等待了${ms}毫秒`);
})
// 等待了1000毫秒
// 等待了1000毫秒
// 等待了2000毫秒
// 等待了2000毫秒
// 等待了undefined毫秒
let result = 0 //定义全局变量初值
function calc(num) {
return new Promise((resolve, reject) => {
console.log(result);
resolve(num)
})
}
calc(1) //执行new Promise,返回一个Promise对象,并立即执行函数,输出0
.then((num) => { //num = 1
result += num //result = 0+1 =1
return calc(2) // 执行calc(2),传入参数num = 2
// 执行new Promise,返回一个新Promise对象,并立即执行函数,输出1
})
.then((num) => { //num = 2
result -= num //result = 1-2 =-1
return calc(3)// 执行calc(3),传入参数num = 3
// 执行new Promise,返回一个新Promise对象,并立即执行函数,输出-1
})
.then((num) => { //num = 3
result *= num //result = -1 * 3 =-3
return calc(4)// 执行calc(4),传入参数num = 4
// 执行new Promise,返回一个新Promise对象,并立即执行函数,输出-3
})
// 0
// 1
// -1
// -3
then里的参数是可选的,第一个参数是成功的回调函数resolve,第二个参数是失败的回调函数reject,catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。
Promise 新建后就会立即执行
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
上面代码中,Promise 新建后立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。