如何基于Promise取消一个Promise(取消异步请求)

使用本文记录一下如何基于Promise取消一个Promise(取消异步请求)

前言

使用本文记录一下如何基于Promise取消一个Promise(取消异步请求),还有其他的关于fetch的AbortController,axios的cancelToken,还有ajax的等等,这些以后慢慢补上,目前本文不做讲解。

基于Promise.race取消请求


data: {},
    testPromiseAbortByRace: function () {
        /*
         * race的原理是:n个promise竞速,其中任何一个执行完毕(resolve/reject)都会执行后续的then/catch
         * 利用race原理:
         * 1.将每个promise进行包装,每个promise都会和一个默认的promise竞速;
         * 2.并且将我们初始化的promise的reject方法返回到上端,作为取消的方法,上端只要调用该方法,该promise立马就会reject,竞速结束,以达到取消请求的目的;
         */
        function decoratePromise(promise) {
            //初始化
            var obj = {};
            var promiseFlag = new Promise(function (resolve, reject) {
                //存储
                obj.abort = reject;
            });
            //竞速
            obj.promise = Promise.race([promise, promiseFlag]);
            //返回
            return obj;
        }
        //模拟请求
        var p1 = new Promise(function (resolve, reject) {
            //提示
            testPromiseAbortIndexService.log('进入promise,5s后打印');
            setTimeout(function () {
                //成功
                resolve('5s已到,promise已打印完毕');
            },
                5000);
        });
        //装饰请求
        var p1Decorated = decoratePromise(p1);
        p1Decorated.promise.then(function (successResult) {
            //提示
            testPromiseAbortIndexService.log('请求成功:' + successResult);
        }).catch(function (errorResult) {
            //提示
            testPromiseAbortIndexService.log('请求失败:' + errorResult);
        });
        //赋值
        testPromiseAbortIndexService.data.promiseDecorated = p1Decorated;
    },
    cancelForTestPromiseAbortByRace: function () {
        //提示
        testPromiseAbortIndexService.log('即将取消请求,abort');
        //取消请求
        testPromiseAbortIndexService.data.promiseDecorated.abort('取消请求,abort');
    },

封装公共方法将异步逻辑包装在Promise请求中实现取消请求


testPromiseAbortBySelf: function () {
        /*
         * 封装公共方法将逻辑包装到promise内:
         * 1.将逻辑包装到promise里面,并且将reject方法返回到上端,作为取消的方法,上端只要调用该方法,该promise立马就会reject,以达到取消请求的目的;
         * 2.reject通过不同参数区分,到底是取消,还是真正的执行失败reject;
         */
        function decoratePromiseBySelf(action) {
            //初始化
            var obj = {};
            var newPromise = new Promise(function (resolve, reject) {
                //存储
                obj.resolve = resolve;
                obj.reject = reject;
                //调用
                action && action(resolve, reject);
            });
            //返回
            return {
                promise: newPromise,
                abort: function (result) {
                    //取消
                    obj.reject({
                        name: 'abort',
                        message: result,
                        aborted: true
                    });
                }
            };
        }
        //模拟请求
        var p1 = function (resolve, reject) {
            //提示
            testPromiseAbortIndexService.log('进入promise,5s后打印');
            setTimeout(function () {
                //失败
                reject('参数不能为空');
            },
                3000);
            //setTimeout(function () {
            //    //成功
            //    resolve('5s已到,promise已打印完毕');
            //},
            //    5000);
        };
        //装饰请求
        var p1Decorated = decoratePromiseBySelf(p1);
        p1Decorated.promise.then(function (successResult) {
            //提示
            testPromiseAbortIndexService.log('请求成功:' + successResult);
        }).catch(function (errorResult) {
            //是否取消
            var isAbort = errorResult.aborted === true;
            if (isAbort) {
                //提示
                testPromiseAbortIndexService.log('取消请求:' + errorResult.message);
            } else {
                //提示
                testPromiseAbortIndexService.log('请求失败:' + errorResult);
            }
        });
        //赋值
        testPromiseAbortIndexService.data.promiseDecoratedBySelf = p1Decorated;
    },
    cancelForTestPromiseAbortBySelf: function () {
        //提示
        testPromiseAbortIndexService.log('即将取消请求,abort');
        //取消请求
        testPromiseAbortIndexService.data.promiseDecoratedBySelf.abort('取消请求,abort');
    },

完整代码如下


@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <div>
        <input type="button" value="使用race原理实现取消promise" id="btnTestPromiseAbortByRace" />
        <input type="button" value="取消请求" id="btnCancelForTestPromiseAbortByRace" />
        <br /><br />
        <input type="button" value="通过包装promise实现取消promise" id="btnTestPromiseAbortBySelf" />
        <input type="button" value="取消请求" id="btnCancelForTestPromiseAbortBySelf" />
        <ul id="msgContainer"></ul>
    </div>
</body>
</html>
<script src="~/lib/jquery-3.4.1.min.js"></script>
<script src="~/Scripts/lingbugUtil.js"></script>
<script src="~/Scripts/testPromiseAbortIndex.js"></script>


var testPromiseAbortIndexService = {
    run: function () {
        //初始化按钮
        $('#btnTestPromiseAbortByRace').on('click', testPromiseAbortIndexService.testPromiseAbortByRace);
        //初始化按钮
        $('#btnCancelForTestPromiseAbortByRace').on('click', testPromiseAbortIndexService.cancelForTestPromiseAbortByRace);
        //初始化按钮
        $('#btnTestPromiseAbortBySelf').on('click', testPromiseAbortIndexService.testPromiseAbortBySelf);
        //初始化按钮
        $('#btnCancelForTestPromiseAbortBySelf').on('click', testPromiseAbortIndexService.cancelForTestPromiseAbortBySelf);
    },
    data: {},
    testPromiseAbortByRace: function () {
        /*
         * race的原理是:n个promise竞速,其中任何一个执行完毕(resolve/reject)都会执行后续的then/catch
         * 利用race原理:
         * 1.将每个promise进行包装,每个promise都会和一个默认的promise竞速;
         * 2.并且将我们初始化的promise的reject方法返回到上端,作为取消的方法,上端只要调用该方法,该promise立马就会reject,竞速结束,以达到取消请求的目的;
         */
        function decoratePromise(promise) {
            //初始化
            var obj = {};
            var promiseFlag = new Promise(function (resolve, reject) {
                //存储
                obj.abort = reject;
            });
            //竞速
            obj.promise = Promise.race([promise, promiseFlag]);
            //返回
            return obj;
        }
        //模拟请求
        var p1 = new Promise(function (resolve, reject) {
            //提示
            testPromiseAbortIndexService.log('进入promise,5s后打印');
            setTimeout(function () {
                //成功
                resolve('5s已到,promise已打印完毕');
            },
                5000);
        });
        //装饰请求
        var p1Decorated = decoratePromise(p1);
        p1Decorated.promise.then(function (successResult) {
            //提示
            testPromiseAbortIndexService.log('请求成功:' + successResult);
        }).catch(function (errorResult) {
            //提示
            testPromiseAbortIndexService.log('请求失败:' + errorResult);
        });
        //赋值
        testPromiseAbortIndexService.data.promiseDecorated = p1Decorated;
    },
    cancelForTestPromiseAbortByRace: function () {
        //提示
        testPromiseAbortIndexService.log('即将取消请求,abort');
        //取消请求
        testPromiseAbortIndexService.data.promiseDecorated.abort('取消请求,abort');
    },
    testPromiseAbortBySelf: function () {
        /*
         * 封装公共方法将逻辑包装到promise内:
         * 1.将逻辑包装到promise里面,并且将reject方法返回到上端,作为取消的方法,上端只要调用该方法,该promise立马就会reject,以达到取消请求的目的;
         * 2.reject通过不同参数区分,到底是取消,还是真正的执行失败reject;
         */
        function decoratePromiseBySelf(action) {
            //初始化
            var obj = {};
            var newPromise = new Promise(function (resolve, reject) {
                //存储
                obj.resolve = resolve;
                obj.reject = reject;
                //调用
                action && action(resolve, reject);
            });
            //返回
            return {
                promise: newPromise,
                abort: function (result) {
                    //取消
                    obj.reject({
                        name: 'abort',
                        message: result,
                        aborted: true
                    });
                }
            };
        }
        //模拟请求
        var p1 = function (resolve, reject) {
            //提示
            testPromiseAbortIndexService.log('进入promise,5s后打印');
            setTimeout(function () {
                //失败
                reject('参数不能为空');
            },
                3000);
            //setTimeout(function () {
            //    //成功
            //    resolve('5s已到,promise已打印完毕');
            //},
            //    5000);
        };
        //装饰请求
        var p1Decorated = decoratePromiseBySelf(p1);
        p1Decorated.promise.then(function (successResult) {
            //提示
            testPromiseAbortIndexService.log('请求成功:' + successResult);
        }).catch(function (errorResult) {
            //是否取消
            var isAbort = errorResult.aborted === true;
            if (isAbort) {
                //提示
                testPromiseAbortIndexService.log('取消请求:' + errorResult.message);
            } else {
                //提示
                testPromiseAbortIndexService.log('请求失败:' + errorResult);
            }
        });
        //赋值
        testPromiseAbortIndexService.data.promiseDecoratedBySelf = p1Decorated;
    },
    cancelForTestPromiseAbortBySelf: function () {
        //提示
        testPromiseAbortIndexService.log('即将取消请求,abort');
        //取消请求
        testPromiseAbortIndexService.data.promiseDecoratedBySelf.abort('取消请求,abort');
    },
    log: function (msg) {
        //显示
        $('#msgContainer').append('<li>' + lingbugUtil.dateFormat(new Date(), 'yyyy-MM-dd HH:mm:ss.fff') + ':' + msg + '</li>');
    }
};

//执行
testPromiseAbortIndexService.run();

End~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值