使用本文记录一下如何基于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~