这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
前面写了Promise的入门和相关方法的使用,其中讲了Promise的作用、状态、基本使用、执行顺序、相关方法的使用,需要的童鞋请移步。
这篇文章写下Promise需要注意的问题:
- 如何改变Promise的状态?
- 一个Promise指定多个成功/失败回调都会被调用吗?
- 改变Promise状态和指定回调函数谁先谁后?
- then()返回的新promise的结果状态由什么决定?
- Promise如何串连多个操作任务?
- 如何中断Promise链?
一、如何改变Promise的状态
- resolve(value): 如果当前是pending状态则变为fulfilled状态;
- reject(reason): 如果当前是pending状态则变为rejected状态;
- 抛出异常:如果当前是pending状态则变为rejected状态。
const p = new Promise(() => {
// resolve(1); // Promise变为fulfilled状态
// reject(2); // Promise变为rejected状态
throw new Error("出错了"); // Promise变为rejected状态
});
二、一个Promise指定多个成功/失败回调都会被调用吗
一个Promise指定多个成功/失败回调都会被调用。
const p = new Promise(resolve => {
resolve(1);
});
p.then(value => {
console.log("第1个:" + value);
});
p.then(value => {
console.log("第2个:" + value);
});
执行结果:
// 第1个回调函数被调用:1
// 第2个回调函数被调用:1
从例子中可以看出,p的两个then方法中的回调函数都被调用了,获取到的返回值都为1,。
三、改变Promise状态和指定回调函数谁先谁后
改变Promise状态和指定回调函数谁先谁后?
- 都有可能,正常状态下是 先指定回调函数 再改变状态,但也可以先改变状态再指定回调函数。
- 如何先改变状态再指定回调函数?
- 在执行器中直接调用resolve()/reject()
- 延迟调用then方法
方法一例子:
const p = new Promise(resolve => {
resolve(1);
}).then(value => {
console.log(value);
});
该例子中执行器中用同步的方式resolve(1),所以先改变了状态,再用then方法指定了回调函数。
方法二例子:
const p = new Promise(resolve => {
resolve(1);
});
setTimeout(() => {
p.then(value => {
console.log(value);
});
}, 100);
该例子中执行器中用同步的方式resolve(1),所以先改变了状态,再使用setTimeout方法来延迟then方法指定回调函数。
- 什么时候才能得到数据?
- 如果先指定回调,那当状态发生改变时,回调函数就会调用,得到数据。
- 如果先改变状态,那当指定回调是,回调函数调用,得到数据。
四、then()返回的新promise的结果状态由什么决定
由then指定的回调函数执行的结果决定:
- 若抛出异常,则新promise状态变为rejected,reason为抛出的异常。
- 若返回的是非promise的任意值,则新promise状态变为fulfilled,value为返回的值。
- 若返回的是另一个新的promise,则此promise的结果就会成为新promise的结果。 例子:
const p = new Promise(resolve => {
reject(1);
}).then(
val => {
console.log("resolve1:", val);
},
reason => {
console.log("reject1:", reason);
// 无返回值,下一个then接收到的就是undefined
}
).then(
val => {
console.log("resolve2:", val);
},
reason => {
console.log("reject2:", reason);
}
);
执行结果:
// reject1: 1
// resolve2: undefined
p中reject(1),使得第一个then方法接收到异常,执行了第二个参数中的回调函数。
第一个then执行完后没有异常,返回一个新的返回值为undefined的Promise,所以第二个then方法调用第一个参数的回调函数。
五、Promise如何串连多个操作任务
通过then的链式调用串连多个同步/异步任务。 例子:
const p = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("异步任务1");
resolve(1);
});
})
.then(val => {
console.log("异步任务1的结果:", val);
return 2;
})
.then(val => {
// 下个then会等待这个promise执行完再执行
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("同步任务2的结果:", val);
resolve(3);
}, 100);
});
})
.then(val => {
console.log("异步任务3的结果:", val);
});
执行结果:
// 异步任务1
// 异步任务1的结果: 1
// 同步任务2的结果: 2
// 异步任务3的结果: 3
第一个then方法中会等待前面Promise执行完后再执行。 then方法的回调函数中无法使用resolve来返回值,所以使用return来返回。 第二个then方法中返回一个新的Promise实例,第三个then会等到此Promise实例完成后再执行。
六、如何中断Promise链
采用链式写法,then方法后面会再调用另一个then方法,如果没有中断,将会一直调用,直到所有then方法都完成。那如何中断这条Promise链呢? 在回调函数中返回一个pending状态的promise对象即可中断promise链。
例子:
const p = new Promise((resolve, reject) => {
resolve(1);
})
.then(val => {
console.log(val);
// 返回一个pending状态的promise对象,后面的then方法将不会执行
return new Promise(() => {});
})
.then(val => {
console.log("不会执行了:", val);
});
执行结果: // 1
第一个then方法中返回了一个pending状态的promise对象,一直没有返回结果, 第二个then方法一直等不到返回结果,所以并不会被执行,所以起到了中断Promise的效果。