接着Promise(2):手动实现Promise,为Promise添加扩展方法
1、静态方法
resolve
用于包装任意对象为promise对象,返回一个新的promise,并且状态是resolved
static resolve(value) {
if (value instanceof this) {
return value;
}
return executeCallback.call(new MPromise(), 'resolve', value);
}
reject
用于包装任意对象为promise对象,返回一个新的promise,并且状态是rejected
static reject(reason) {
if (reason instanceof this) {
return reason;
}
return executeCallback.call(new MPromise(), 'reject', reason);
}
all
- 如果全部成功则获得成功的结果组成的数组对象,如果失败,则获得失败的信息
- 返回一个新的Promise对象
- 即要保证全部成功,又要保证按数组里原来的顺序返回结果
static all(iterable){
return new MPromise((resolve, reject) => {
if (!iterable || !Array.isArray(iterable)){
return reject(new TypeError('all param must be an array'))
}
const len = iterable.length;
let result = Array(len); //保证顺序
let called = false; //结果不可逆
let current = 0;
if (len == 0){
return resolve([]);
}
iterable.forEach((v, i) => {
MPromise.resolve(v).then((value)=>{
result[i] = value;
current++;
if (!called && current === len) {
called = true;
resolve(result);
}
}, (err)=>{
if (!called) {
called = true;
return reject(err);
}
});
});
});
}
测试例子
function fn1() {
return new MPromise(resolve => setTimeout(() => resolve(1), 3000))
}
function fn2() {
return new MPromise(resolve => setTimeout(() => resolve(2), 2000))
}
MPromise.all([fn1(), fn2()]).then(res => {
console.log(res);
}, err => {
console.log(err);
});
//[1,2]
race
- 如果某个promise的状态率先改变,就获得改变的结果
- 返回一个新的Promise对象
- 在调用过程中会使用 Promise.resolve(value) 转换成Promise对象)
static race(iterable) {
return new MPromise((resolve, reject) => {
if (!iterable || !Array.isArray(iterable)) {
return reject(new TypeError('race param must be an array'))
}
const len = iterable.length;
let called = false;
if (len == 0) {
return resolve();
}
iterable.forEach((v, i)=> {
MPromise.resolve(v).then((value)=> {
if (called) return;
called = true;
return resolve(value);
}, (reason)=> {
if (called) return;
called = true;
return reject(reason);
});
});
});
}
stop
这里利用,then 方法中对状态的要求必须不是 Pending 状态的处理才会立即执行回调,在 promise链 中返回一个初始状态的 Promise对象,便可以中断后面回调的执行
static stop(){
return new Promise();
}
例子
function fn1() {
return new MPromise(resolve => setTimeout(() => resolve(1), 1000))
}
function fn2() {
return new MPromise(resolve => setTimeout(() => resolve(2), 1000))
}
MPromise.all([fn1(), fn2()]).then(res => {
console.log(res);
return MPromise.stop();
}, err => {
console.log(err);
}).wait(3000).then(function (res) {
console.log(res);
});
deferred
Deferred 的简称,叫延迟对象,其实是 new Promise() 的语法糖 与Promise的关系
- Deferred 拥有 Promise
- Deferred 具备对 Promise的状态进行操作的特权方法
- Promise 代表了一个对象,这个对象的状态会在未来改变
- Deferred对象 表示了一个处理没有结束,在状态发生改变时,再使用Promise来处理结果
优缺点
- 不用使用大括号将逻辑包起来,少了一层嵌套
- 但是缺少了Promise的错误处理逻辑
static deferred() {
let defer = {};
defer.promise = new MPromise((resolve, reject)=> {
defer.resolve = resolve;
defer.reject = reject;
});
return defer;
}
例子
function fn(){
let deferred = MPromise.deferred();
setTimeout(() => {
deferred.resolve('xxxxxx');
}, 3000);
return deferred.promise;
}
fn().then((res) => {
console.log(res);
})
timeout
如一个异步请求,如果超时,取消息请求,提示消息或重新请求
static timeout(promise, ms){
return this.race([promise, this.reject().wait(ms)]);
}
sequene
用于按顺序执行一系列的promise,接收的函数数组,并不是Promise对象数组,其中函数执行时就返回Promise对象,用于有互相依赖的promise任务
static sequence(tasks){
return tasks.reduce((prev, next)=> {
return prev.then(next).then((v)=> v);
}, this.resolve());
}
例子
function fn1() {
return new MPromise(resolve => {
setTimeout(() => {
resolve(1)
}, 1000)
});
}
function fn2(data) {
return new MPromise(resolve => {
setTimeout(() => {
resolve(data + 5)
}, 1000)
});
}
MPromise.sequence([fn1, fn2]).then(res => {
console.log(res);
return 'xxxx';
}, err => {
console.log(err);
})
实例方法
wait
- 保证链式调用,必须返回新的promise
- 并且上一步的成功和失败的消息不能丢失,继续向后传递,这里只做延迟处理
wait(ms) {
return this.then((value)=>{
return new MPromise(function (resolve, reject) {
setTimeout(() => resolve(value), ms);
});
}, (reason)=>{
return new MPromise(function(resolve, reject){
setTimeout(() => reject(reason), ms);
});
});
}
always
无论成功还是失败最终都会调用 always 中注册的回调
always(fn) {
return this.then((value)=>{
return fn(value), value;
}, (reason) => {
throw fn(reason), reason;
});
}
done
- done方法并不返回promise对象,也就是done之后不能使用 then或catch了,其主要作用就是用于将 promise链 中未捕获的异常信息抛至外层,并不会对错误信息进行处理。
- done方法必须应用于promise链的最后
done(onResolved, onRejected) {
this.then(onResolved, onRejected).catch((error)=> {
setTimeout(() => {
throw error;
}, 0);
});
}