# 1. 实现 Promise
// 链式调用 输出 200
const p3 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log(res), err => console.log(err))
// 链式调用 输出300
const p4 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => new Promise((resolve, reject) => resolve(3 * res)), err => console.log(err))
.then(res => console.log(res), err => console.log(err))
- 1、then方法本身会返回一个新的Promise对象
- 2、如果返回值是promise对象,返回值为成功,新promise就是成功
- 3、如果返回值是promise对象,返回值为失败,新promise就是失败
- 4、如果返回值非promise对象,新promise对象就是成功,值为此返回值
function resolvePromise(promise2, x, resolve, reject) {
// 判断x是不是promise
// 规范中规定:我们允许别人乱写,这个代码可以实现我们的promise和别人的promise 进行交互
if (promise2 === x) { // 不能自己等待自己完成
return reject(new TypeError('循环引用'));
};
// x是除了null以外的对象或者函数
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
let called;// 防止成功后调用失败
try { // 防止取then是出现异常 object.defineProperty
const { then } = x;// 取x的then方法 {then:{}}
if (typeof then === 'function') { // 如果then是函数就认为他是promise
// call第一个参数是this,后面的是成功的回调和失败的回调
then.call(x, (y) => { // 如果Y是promise就继续递归promise
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, (r) => { // 只要失败了就失败了
if (called) return;
called = true;
reject(r);
});
} else { // then是一个普通对象,就直接成功即可
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else { // x = 123 x就是一个普通值 作为下个then成功的参数
resolve(x);
}
}
class MyPromise {
constructor(executor) {
// 默认状态是等待状态
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 存放成功的回调
this.onResolvedCallbacks = [];
// 存放失败的回调
this.onRejectedCallbacks = [];
const resolve = (data) => { // this指的是实例
if (this.status === 'pending') {
this.value = data;
this.status = 'resolved';
// while(this.onResolvedCallbacks.length) {
// this.onRejectedCallbacks.shift()(this.value)
// }
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
// while (this.onRejectedCallbacks.length) {
// this.onRejectedCallbacks.shift()(this.reason)
// }
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try { // 执行时可能会发生异常
executor(resolve, reject);
} catch (e) {
reject(e);// promise失败了
}
}
then(onFuiFilled, onRejected) {
// 防止值得穿透
onFuiFilled = typeof onFuiFilled === 'function' ? onFuiFilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected : (err) => {
throw err;
};
let promise2;// 作为下一次then方法的promise
if (this.status === 'resolved') {
promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
// 成功的逻辑 失败的逻辑
const x = onFuiFilled(this.value);
// 看x是不是promise 如果是promise取他的结果 作为promise2成功的的结果
// 如果返回一个普通值,作为promise2成功的结果
// resolvePromise可以解析x和promise2之间的关系
// 在resolvePromise中传入四个参数,第一个是返回的promise,第二个是返回的结果,第三个和第四个分别是resolve()和reject()的方法。
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
if (this.status === 'rejected') {
promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
// 在resolvePromise中传入四个参数,第一个是返回的promise,第二个是返回的结果,第三个和第四个分别是resolve()和reject()的方法。
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
// 当前既没有完成也没有失败
if (this.status === 'pending') {
promise2 = new MyPromise((resolve, reject) => {
// 把成功的函数一个个存放到成功回调函数数组中
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFuiFilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// 把失败的函数一个个存放到失败回调函数数组中
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
});
}
return promise2;// 调用then后返回一个新的promise
}
catch(onRejected) {
// catch 方法就是then方法没有成功的简写
return this.then(null, onRejected);
}
}
MyPromise.all = function (promises) {
// promises是一个promise的数组
return new MyPromise((resolve, reject) => {
const arr = []; // arr是最终返回值的结果
let i = 0; // 表示成功了多少次
function processData(index, data) {
arr[index] = data;
if (++i === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then((data) => {
processData(i, data);
}, reject);
}
});
};
// 只要有一个promise成功了 就算成功。如果第一个失败了就失败了
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
};
// 生成一个成功的promise
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => resolve(value));
};
// 生成一个失败的promise
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason));
};
MyPromise.defer = MyPromise.deferred = function () {
const dfd = {};
dfd.MyPromise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
// 测试
const p = new MyPromise((resolve) => {
console.log('1');
resolve(2);
});
const a = p.then((res) => {
console.log('3', res);
return res * 2;
});
console.log('a', a);
a.then((res) => {
console.log('resresres', res);
});
参考:
- Promise不会??看这里!!!史上最通俗易懂的Promise!!! (opens new window)
- 看了就会,手写Promise原理,最通俗易懂的版本!! (opens new window)
# 2. 实现 Promise.all
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的
promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);
如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
Promise.myAll = function (arr) {
return new Promise((resolve, reject) => {
const results = [];
let count = 0;
if (!arr.length) {
return Promise.resolve([]);
}
for (let i = 0; i < arr.length; i++) {
arr[i].then((res) => {
results[i] = res;
count += 1;
if (count == arr.length - 1) {
resolve(results);
}
}).catch((err) => {
reject(err);
});
}
});
};
const promise1 = new Promise((resolve) => {
console.log('1')
setTimeout(() => {
resolve(1)
}, 100)
})
const promise2 = new Promise((resolve) => {
resolve(2)
})
Promise.myAll([promise1, promise2]).then(res => {
console.log('res', res)
})
# 3. 实现 Promise.race
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,
返回的 promise 就会解决或拒绝。
Promise.myRace = function (arr) {
return new Promise((resolve, reject) => {
for (let i =0; i< arr.length;i++) {
arr[i].then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
}
})
}
测试:
const promise1 = new Promise((resolve) => {
console.log('1')
setTimeout(() => {
resolve(1)
}, 100)
})
const promise2 = new Promise((resolve) => {
resolve(2)
})
Promise.myRace([promise1, promise2]).then(res => {
console.log('resR', res)
})
# 4. 实现 Promise.allSettled
Promise.allSettled() 方法返回一个在所有给定的 promise 已被决议或被拒绝后决议的 promise,
并带有一个对象数组,每个对象表示对应的promise 结果。
Promise.newAllSettled = function (promiseArr) {
let results = [];
return new Promise((resolve, reject) => {
let i = 0, n = 0;
// 运行所有的 Promise
while (n < promiseArr.length) {
promiseArr[n].then(res => {
// 当有 Promise 被 resolve 之后,记录 resolve 值和状态,已决 Promise 计数加一
results.push({value: res, status: 'fulfilled'});
i++;
// 全部 Promise 已决,resolve
if (i === promiseArr.length) {
resolve(results);
}
}).catch(err => {
// 当有 Promise 被 reject 后,记录 reject 值和状态,并且已决的 Promise 计数加一
results.push({value: err, status: 'rejected'});
i++;
if (i === promiseArr.length) {
resolve(results);
}
});
n++;
}
})
};
# 5. 实现 Promise.finally
- 接收一个回调函数,但无参数接收
- 无论成功失败状态,都会执行finally
Promise.prototype.finally = function(callback) {
return this.then(res => {
callback()
return res
}, err => {
callback()
throw err
})
}
参考:
← 跨域 vue-reactive →