为Promise增加abort方法

对于Promise而言只有三个状态: PendingResolveReject。在任意时刻,一个Promise只能是处于这三个状态中的任意一个,且一旦状态变为Resolve或者Reject之后,状态不能再修改。 有时候我们需要在Promsie从Pending状态变成Resolve或者Reject之前,停止执行对应的Promsie。就像是将Promise的状态修改为Stop或者Abort。常见的例子:

  1. 发送异步请求时,在请求返回之前直接结束当前任务的逻辑
  2. 多个任务并发时,停止执行未处理完成的任务

既然Promise不支持,那我们能否通过其提供的接口来实现一个Abort方法呢?可以使用Promise.race方法的特点来模拟实现。Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); Promise.race([promise1, promise2]).then((value) => { console.log(value); // Both resolve, but promise2 is faster });

可以使用Promise.race()来构造一个“竞争关系”,将想abort的Promise和一个内置的Promise,放在race中执行,而内置的Promsie立马返回 Resovled 或者 Reject ,从而将另外一个Pomise的执行停止。

let PromiseWithAbort = function(promise){ let _abort = null; let Pabort = new Promise((resolved, reject)=>{ _abort = function(reason ='abort !'){ console.warn(reason); reject(reason); } }); let race = Promise.race([promise, Pabort]); race.abort = _abort; console.log(promise, Pabort); return race; } let p1= new Promise(res=>{ setTimeout(()=>{ res('p1 success'); },2000) }) let testP = PromiseWithAbort(p1); testP.then(res=>{ console.log('success:', res); },error=>{ console.log('error:', error); }) testP.abort();

或者重新包装一个新的Promise

class PromiseWithAbort { constructor(fn){ let _abort = null; let _p = new Promise((resolved, reject)=>{ fn.call(null,resolved, reject); _abort = function(error = 'abort'){ reject(error); } }) _p.abort = _abort; return _p; } } let testP = new PromiseWithAbort((resolved, reject)=>{ setTimeout(() => { res(1); },1000); }); testP.then( (resolved)=>{ console.log('resolved:', resolved); }, (reject) =>{ console.log('reject:', reject); }); testP.abort(); //结果: rej: abort