原文地址

Promise.race

// `delay`毫秒后执行resolve
function timerPromisefy(delay) {
    return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(delay);
        }, delay);
    });
}
// 任何一个promise变为resolve或reject 的话程序就停止运行
Promise.race([
    timerPromisefy(1),
    timerPromisefy(32),
    timerPromisefy(64),
    timerPromisefy(128)
]).then(function (value) {
    console.log(value);    // => 1
});

Promise.race 是当接受的参数数组中有一个promise对象进入fulfilled或者rejected状态的时候就停止运行。此时,由于只有一个promise的状态能够确定,所以then执行的是唯一那个确定状态的resolve函数,而不会执行其他的resolve,但是并不会阻止其他promise的执行。

关于promise.race的使用

我们知道promise.race如果参数promise数组中只要有一个promise状态改变就会执行后续的回调,那么如果参数数组中最先返回的是失败状态,那就直接走到了rejected,其实这违背了我们使用的初衷。不过参数中promise状态的改变是由开发者控制的,如果不想发生这样的情况,可以在promise定义的时候设置好错误处理,保证promise.race需要解析的一定是确定的状态。

在实际应用中,promise.race常用来设置超时操作,比如接口请求超时等。而且要注意不要给promise.race传入空数组,那么这个promise将不会被解析。

为什么使用then每次需要创建一个新的promise

如果没有创建新的promise,每次都是返回之前的promise,那么当最开始promise的状态发生改变之后,后续的promise状态其实已经固定不会再改变了。这就无法实现promise的功能,所以每次的promise对象都应该相互独立,互相不影响。

看似矛盾的问题

let promise1 = Promise.resolve()
let promise2 = promise1.then(function foo(value) {
  return Promise.reject(3)
})

执行结果:

执行结果

看似矛盾,promise1明明执行了成功的回调,为什么最后promise2的状态是rejected。原因是在调用then的时候,创建了新的promise,此时与promise1已经没有关系了,返回的时候改变的是新创建的promise的状态,变为rejected。

不过看了下Promises/A+的标准,这边叙述貌似还有些需要再研究确认一下的地方。

标准中说,如果onFulfilled或者onRejected返回一个promise对象(thenable对象),那么promise2会接受x的状态。上述代码似乎执行结果与标准中的叙述有矛盾,这个问题还需要再思考下。

标准

标准

【思考】

这个其实并不是矛盾,promise2接受的是返回的promise的状态,与原来的没有关系。这边确实很容易混淆。

关于promise.then链式调用时参数value的传递
promise1.then(function func(value){
    console.log('1-'+value)
    return value * 2
}).then(function func(value){
    console.log('2-'+value);
}).then(function func(value){
    console.log('3-'+value)
})

执行结果

执行结果

可以看到,如果不使用没有return,那么上一个then的执行结果并不会传递到下一个then当中。

【思考】

有些问题如果觉得有疑惑或者弄不太清,那就一定要想着写个demo运行看下,不能靠直觉或者思维定势去想结果,毕竟~实践是检验真理的唯一标准~


Tenacity
77 声望4 粉丝

有志者立长志,无志者常立志。