JavaScript 中断Promise链方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37263637/article/details/83582475

1 Promise

Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件,在ES6得到支持。
且具有以下特点:
对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

一个简单例子Promise 的例子。

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

2 Promise链及如何终止

2.1 现象

主要问题是:链式调用时,想在下层返回resolve的情况下,需要在中途得到某种resolve结果就终止调用链。(PS:下层可能是调用其他人编写模块,比如参数不对,它仍会返回resolve,出现错误才会reject,本身下层Promise 返回reject是可以打断调用链的)

下面有个链式调用Promise的测试函数

const promiseFun = function(param1){
    return new Promise((resolve, reject)=>{
        resolve(param1);
    });
}
const promiseTest = function(param1, param2){
    return new Promise((resolve, reject)=>{
        promiseFun(1).then((number)=>{
            console.info(`fun1 result:${number}`);
            return promiseFun(2);
        }).then((number)=>{
            console.info(`fun2 result:${number}`);
            return promiseFun(3);
        }).then((number)=>{
            console.info(`fun3 result:${number}`);
            return promiseFun(4);
        }).then((number)=>{
            console.info(`fun4 result:${number}`);
        }).catch((err)=>{
            console.info(`promiseTest error:${err}`);
        });
    });        
}
promiseTest('1','2').then((number)=>{
    console.info(`promiseTest:${number}`);
}).catch((err)=>{
    console.info(`promiseTest failed:${err}`);
});

现在遇到的一个问题是,比如我们在fun2时,我们调用reject 想终止该链式调用,但实际的结果是仍然会跑到console.info(fun3 result:${number})及console.info(fun4 result:${number})。

即:

        promiseFun(1).then((number)=>{
            console.info(`fun1 result:${number}`);
            return promiseFun(2);
        }).then((number)=>{
            console.info(`fun2 result:${number}`);
           if(number === 2){
                reject(number)
            }
            else{
                return promiseFun(3);
            }
        }).then((number)=>{
            console.info(`fun3 result:${number}`);
            return promiseFun(4);
        }).then((number)=>{
            console.info(`fun4 result:${number}`);
        }).catch((err)=>{
            console.info(`promiseTest error:${err}`);
        });

2.2 原因

Promise的then方法接收两个参数:
Promise.prototype.then(onFulfilled, onRejected)
若onFulfilled或onRejected是一个函数,当函数返回一个新Promise对象时,原Promise对象的状态将跟新对象保持一致。
来自:https://promisesaplus.com/

解释下原因:
1 我们编写then函数一般情况下只写了onFulfilled,也就是resolve结果的处理函数,而onRejected处理一般情况下都是没有编写的,所以链式调用抛出的reject,因为链式调用上均没有捕获到,根据 原Promise对象的状态将跟新对象保持一致的原理就会一路传递到catch中进行处理。
2 为什么我们链式调用中reject没有作用,因为reject仅仅改变的是外层包的promiseTest 返回Promise状态。而在第二个链式调用then,没做处理,所以第三个链式继承了第一个链式调用返回的Promise 的resolve状态,导致链式调用继续向下运行。

2.3 解决方案

而针对上面的问题,我们想要在resolve的情况下,中断或终止链式调用。
还是基于Promise的特点:原Promise对象的状态将跟新对象保持一致。

扫描二维码关注公众号,回复: 4633266 查看本文章

我们仅需要在链式调用中,返回一个pending 状态或reject状态的Promise对象即可。后面then 所有resolve(onFulfilled)的处理函数就都不会跑到了。即:

return (new Promise((resolve, reject)=>{}));//返回pending状态
return (new Promise((resolve, reject)=>{rejcet()}));//返回reject状态 会被最后catch捕获。

在测试代码中就想这样

then((number)=>{
            console.info(`fun2 result:${number}`);
           if(number === 2){return (new Promise((resolve, reject)=>{}));
                reject(number)
            }
            else{
                return promiseFun(3);
}

3 参考链接

https://blog.csdn.net/ambit_tsai/article/details/80635594
http://es6.ruanyifeng.com/#docs/promise

猜你喜欢

转载自blog.csdn.net/m0_37263637/article/details/83582475