2019-04-02 Promise 的小技巧和误区
let rt = new Promise((resolve, reject) => {
console.log('start!');
resolve('成功!');
console.log('fine!')
reject('失败!');
});
rt.then(v => {
console.log(v);
}) .catch(err => {
console.log(err)
});
console.log('Hi!');
// start!
// fine!
// Hi!
// 成功!
-
Promise 构造函数
接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数,由 JavaScript 引擎提供,不用自己部署。 -
Promise
一旦新建它就会立即执行,无法中途取消。 -
一旦状态改变,就不会再变,任何时候都可以得到这个结果。
所以,上例中, rt
是一个 Promise
对象,resolve
之后,再调用 reject
是无效的,所以 rt
的状态是 resolved
。
-
调用resolve或reject并不会终结 Promise 的参数函数的执行(所以会打印
fine!
)。 -
上面代码中,Promise 新建后立即执行,所以首先输出的是
start!
。然后输出fine!
,然后输出Hi!
。 -
而then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以
成功!
最后输出。 -
then \ catch 方法调用后,都返回了一个新的promise对象,所以可以链式调用很多个
then
函数。 -
resolve
时可以添加参数,参数会被传递到then
函数作为参数 -
reject
时可以添加参数,参数会被传递到catch
函数作为参数
,
Promise 中需要 return 吗?
上例可以看出,尽管我们无法改变一个已经改变过状态的Promise
,但是reject和resolve都无法让函数剩下的部分终止执行,那函数中 resolve
或者 reject
之后的部分的代码可能会对我们造成干扰。
所以我们最好在 resolve 或者 reject 之后立即停止执行。
resolve('成功!');
return;
或者省一行代码:
return resolve('成功');
那如果是这样呢?
resolve('成功!');
return '失败!';
这个Promise的then
函数的参数仍然是 成功!
,也就是说 return
的值没有任何用。
// 1: 对同一个promise对象同时调用 `then` 方法
var aPromise = new Promise(function (resolve) {
resolve(100);
});
aPromise.then(function (value) {
return value * 2;
});
aPromise.then(function (value) {
return value * 2;
});
aPromise.then(function (value) {
console.log(value); // 100
})
// vs
// 2: 对 `then` 进行 promise chain 方式进行调用
var bPromise = new Promise(function (resolve) {
resolve(100);
});
bPromise.then(function (value) {
return value * 2;
}).then(function (value) {
return value * 2;
}).then(function (value) {
console.log( value); //400
});
第1种写法中并没有使用promise的方法链方式,这在Promise中是应该极力避免的写法。这种写法中的 then 调用几乎是在同时开始执行的,而且传给每个 then 方法的 value 值都是 100 。
第2中写法则采用了方法链的方式将多个 then 方法调用串连在了一起,各函数也会严格按照 resolve → then → then → then 的顺序执行,并且传给每个 then 方法的 value 的值都是前一个promise对象通过 return 返回的值。
也就是说,第一个 then
函数的参数是resolve
传过来的,后面的 then
函数的参数,是前面的then
函数 return
的值
new Promise(() => {console.log(1)}).then(() => {console.log(2)})
这里永远不会打印 2 , promise 的状态永远是 pending 不会改变,所以不会执行 then
里的回调函数