从零手写Promise完整版
- 随着前端技术的不断发展,用户对界面的要求也在不断提高,现在的前端不再是之前的
html+css
, 而是html+css+js
,但是想学好js首先要知道js的核心在于异步,说到异步大部分人第一时间会想到Promise
。 - 那么接下来我们就来学习一下Promise是如何实现的吧。
- 首先我们回顾一下Promise的基本使用
const p = new Promise((resolve,reject)=>{
resolve('返回成功的值')
reject('返回失败的值')
})
p.then(value=>{
console.log(value) // 返回成功的值
})
- new Promise构造函数内的回调数是同步执行的
- then的回调函数,是异步执行的
- 调用resolve/reject后,状态已定,状态不能再改变
- .then每次返回的都是新的Promise
- Promise可以嵌套
接着我们从零开始来实现一下Promise
- 先来实现明确一下基本的结构
(function(window){
// 定义MyPromise构造函数
function MyPromise(executor){
function resolve(value){
}
function reject(reason){
}
executor(resolve,reject)
}
// MyPromise原型链上存在then方法
MyPromise.prototype.then = function(onResolved,onRejected){
}
//MyPromise原型链上存在catch方法
MyPromise.prototype.catch = function(onRejected){
}
//MyPromise实例对象上存在resolve方法
MyPromise.resolve = function(value){
}
//MyPromise实例对象上存在reject方法
MyPromise.reject = function(reason){
}
//MyPromise实例对象上存在all方法
MyPromise.all = function(promises){
}
//MyPromise实例对象上存在race方法
MyPromise.race = function(promises){
}
window.MyPromise = MyPromise;
})(window)
- 明确来了基本的结构后,接下里我们来看看MyPromise构造函数内需要做什么
- 1.定义Promise的初始状态、初始值、存放待执行异步函数的数组
(function(window){
const PENDDING = 'pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function MyPromise(executor){
const self = this;
self.status = PENDDING; //初始状态
self.data = undefined; // 初始值
self.callbacks = []; // 待执行异步回调函数的数组
function resolve(value){
}
function reject(reason){
}
executor(resolve,reject)
}
window.MyPromise = MyPromise;
})(window)
- 根据Promise状态的不同,进行修,赋值,以及立即执行异步回调
(function (window) {
const PENDDING = 'pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 定义MyPromise
function MyPromise(executor) {
const self = this;
self.status = PENDDING;
self.data = undefined;
self.callbacks = [];
function resolve(value) {
self.status = FULFILLED;
self.data = value;
// 立即执行异步回调函数
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value);
})
})
}
function reject(reason) {
self.status = REJECTED;
self.data = reason;
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason);
})
})
}
executor(resolve, reject)
}
window.MyPromise = MyPromise;
- 别忘了Promise 的状态一旦改变就不能再修改了,所以在resolve/reject函数内需要加一个判断
(function (window) {
const PENDDING = 'pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 定义MyPromise
function MyPromise(executor) {
const self = this;
self.status = PENDDING;
self.data = undefined;
self.callbacks = [];
function resolve(value) {
if (self.status !== PENDDING) return;
self.status = FULFILLED;
self.data = value;
// 立即执行异步回调函数
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value);
})
})
}
function reject(reason) {
if (self.status !== PENDDING) return;
self.status = REJECTED;
self.data = reason;
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason);
})
})
}
executor(resolve, reject)
}
window.MyPromise = MyPromise;
- Promise原型链上的then方法,可以接收两个参数(且是回调函数),成功/失败,并且每次返回的都是一个新的Promise
// MyPromise原型链上存在then方法
MyPromise.prototype.then = function (onResolved, onRejected) {
const self = this;
return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象
// 首先判断当前状态
if (self.status === FULFILLED) {
/*
1、返回的Promise的结果是由onResolved/onrejected决定的
2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
3、返回的不是Promise对象 (该值就是Promise的返回结果)
4、抛出异常 异常的值为返回的结果
*/
setTimeout(() => {
try {
const result = onResolved(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
});
} else if (self.status === REJECTED) {
setTimeout(() => {
try {
const result = onRejected(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
});
} else if (self.status === PENDDING) {
self.callbacks.push({
onResolved() {
try {
const result = onResolved(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
},
onRejected() {
try {
const result = onRejected(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
})
}
})
}
- 好的停一下,一步一步讲解
- .then每次都返回一个新的Promise,所以在.then方法里是
> return new MyPromise((resolve,reject)){}
- 每一种状态都存在返回值,并且都能是一下三种情况
- 返回的是Promise对象
- 返回的不是Promise对象
- 抛出异常
- FULFILLED/REJECTED两种状态需要立即执行异步函数
- PENDDING为什么没有立即执行异步函数,因为当状态为PENDDING时就执行then,会先往待执行回调函数的数组(callbacks)内存放这个回调,紧接着在回到Promise的执行其中执行resolve/reject,而上面也写过了,执行resolve/reject会去待执行回调函数的数组内遍历并赋值。
- 好的继续,并且对上面重复的优化一下。
// MyPromise原型链上存在then方法
MyPromise.prototype.then = function (onResolved, onRejected) {
const self = this;
return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象
function handle(callback) {
/*
1、返回的Promise的结果是由onResolved/onrejected决定的
2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
3、返回的不是Promise对象 (该值就是Promise的返回结果)
4、抛出异常 异常的值为返回的结果
*/
try {
const result = callback(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 首先判断当前状态
if (self.status === FULFILLED) {
setTimeout(() => {
thandle(onResolved)
});
} else if (self.status === REJECTED) {
setTimeout(() => {
thandle(onRejected)
});
} else if (self.status === PENDDING) {
self.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onRejected)
}
})
}
})
}
- 防止不穿成功或者失败的回调函数,给成功和失败都给一个默认回调函数
MyPromise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 定义默认回调
onResolved = typeof onResolved === "function" ? onResolved : value => value;
onRejected = typeof onRejected === "function" ? onRejected : reason => {throw reason};
return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象
function handle(callback) {
/*
1、返回的Promise的结果是由onResolved/onrejected决定的
2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
3、返回的不是Promise对象 (该值就是Promise的返回结果)
4、抛出异常 异常的值为返回的结果
*/
try {
const result = callback(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 首先判断当前状态
if (self.status === FULFILLED) {
setTimeout(() => {
thandle(onResolved)
});
} else if (self.status === REJECTED) {
setTimeout(() => {
thandle(onRejected)
});
} else if (self.status === PENDDING) {
self.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onRejected)
}
})
}
})
}
- 接着我们看看catch,其实就是
Promise.prototype.then(undefined,rejected)
- 或者
Promise.prototype.then(null,rejected)
//MyPromise原型链上存在catch方法
MyPromise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}
- 7、接下来实现一下 Promise.resolve/Promise.reject
/MyPromise实例对象上存在resolve方法
MyPromise.resolve = function (value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value)) // 返回一个resolved状态的Promise对象
}
//MyPromise实例对象上存在reject方法
MyPromise.reject = function (reason) {
return new MyPromise((resolve,reject) => reject(reason)); // 返回一个reject状态Promise对象
}
- 接下来实现一下Promise.all/Promise.race
//MyPromise实例对象上存在all方法
MyPromise.all = function (promises) {
let promisesCount = 0
let values = new Array(promises.length);
return new MyPromise((resolve,reject)=>{
promises.forEach((promise,index)=>{
promise.then(value => {
promisesCount++;
values[index] = value;
if (promisesCount === promises.length){
resolve(values);
}
},reason => {
reject(reason);
})
})
})
}
好的,我们来看看Promise.all实现的思路
- Promise.all 传入的是一个数组
- Promise.all返回的是一个数组
- Promise.all传入的数组中,每个Promise对象必须都正确才能返回正确的结果数组
- Promise.all传入的数组中任意一个对象返回错的结果,都会返回错误的结果
- 好的,其实我们还少一个步骤就是Promise.all传入的数组的参数可以不是Promise的实例, 所以数组参数如果不是Promise实例,先调用Promise.resolve
//MyPromise实例对象上存在all方法
MyPromise.all = function (promises) {
let promisesCount = 0
let values = new Array(promises.length);
return new MyPromise((resolve, reject) => {
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(value => {
promisesCount++;
values[index] = value;
if (promisesCount === promises.length) {
resolve(values);
}
}, reason => {
reject(reason);
})
})
})
}
- Promise.race实现
//MyPromise实例对象上存在race方法
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(value => {
resolve(value);
}, reason => {
reject(reason)
})
})
})
}
好的,解释一下,
- Promise.race传入的也是一个数组
- 传入的Promise执行内容相同的情况下,Promise.race返回的结果为数组中的第一个值
- 若传入的Promise执行内容不一致,有先后区分,则结果为执行的最快的一个
- 至此从零手写一个Promise完成了,其中包括
Promise.prototype.thenPromise.prototype.catch
Promise.resolve
Promise.reject
Promise.all
Promise.race
(function (window) {
const PENDDING = 'pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 定义MyPromise
function MyPromise(executor) {
const self = this;
self.status = PENDDING;
self.data = undefined;
self.callbacks = [];
function resolve(value) {
if (self.status !== PENDDING) return;
self.status = FULFILLED;
self.data = value;
// 立即执行异步回调函数
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value);
})
})
}
function reject(reason) {
if (self.status !== PENDDING) return;
self.status = REJECTED;
self.data = reason;
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason);
})
})
}
try{
executor(resolve, reject)
}catch(error){
reject(error)
}
}
// MyPromise原型链上存在then方法
MyPromise.prototype.then = function (onResolved, onRejected) {
const self = this;
// 定义默认回调
onResolved = typeof onResolved === "function" ? onResolved : value => value;
onRejected = typeof onRejected === "function" ? onRejected : reason => {
throw reason
};
return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象
function handle(callback) {
/*
1、返回的Promise的结果是由onResolved/onrejected决定的
2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
3、返回的不是Promise对象 (该值就是Promise的返回结果)
4、抛出异常 异常的值为返回的结果
*/
try {
const result = callback(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 首先判断当前状态
if (self.status === FULFILLED) {
setTimeout(() => {
handle(onResolved)
});
} else if (self.status === REJECTED) {
setTimeout(() => {
handle(onRejected)
});
} else if (self.status === PENDDING) {
self.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onRejected)
}
})
}
})
}
//MyPromise原型链上存在catch方法
MyPromise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
}
//MyPromise实例对象上存在resolve方法
MyPromise.resolve = function (value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value)) // 返回一个resolved状态的Promise对象
}
//MyPromise实例对象上存在reject方法
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason)); // 返回一个reject状态Promise对象
}
//MyPromise实例对象上存在all方法
MyPromise.all = function (promises) {
let promisesCount = 0
let values = new Array(promises.length);
return new MyPromise((resolve, reject) => {
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(value => {
promisesCount++;
values[index] = value;
if (promisesCount === promises.length) {
resolve(values);
}
}, reason => {
reject(reason);
})
})
})
}
//MyPromise实例对象上存在race方法
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(value => {
resolve(value);
}, reason => {
reject(reason)
})
})
})
}
window.MyPromise = MyPromise;
})(window)
- 最后我们用类(class)的方式实现一下
(function (window) {
const PENDDING = 'pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 定义MyPromise
class MyPromise {
constructor(executor) {
const self = this;
self.status = PENDDING;
self.data = undefined;
self.callbacks = [];
function resolve(value) {
if (self.status !== PENDDING) return;
self.status = FULFILLED;
self.data = value;
// 立即执行异步回调函数
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value);
})
})
}
function reject(reason) {
if (self.status !== PENDDING) return;
self.status = REJECTED;
self.data = reason;
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason);
})
})
}
executor(resolve, reject)
}
// MyPromise原型链上存在then方法
then(onResolved, onRejected) {
const self = this;
// 定义默认回调
onResolved = typeof onResolved === "function" ? onResolved : value => value;
onRejected = typeof onRejected === "function" ? onRejected : reason => {
throw reason
};
return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象
function handle(callback) {
/*
1、返回的Promise的结果是由onResolved/onrejected决定的
2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
3、返回的不是Promise对象 (该值就是Promise的返回结果)
4、抛出异常 异常的值为返回的结果
*/
try {
const result = callback(self.data);
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
// 首先判断当前状态
if (self.status === FULFILLED) {
setTimeout(() => {
handle(onResolved)
});
} else if (self.status === REJECTED) {
setTimeout(() => {
handle(onRejected)
});
} else if (self.status === PENDDING) {
self.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onRejected)
}
})
}
})
}
//MyPromise原型链上存在catch方法
catch (onRejected) {
return this.then(null, onRejected);
}
//MyPromise实例对象上存在resolve方法
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value)) // 返回一个resolved状态的Promise对象
}
//MyPromise实例对象上存在reject方法
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason)); // 返回一个reject状态Promise对象
}
//MyPromise实例对象上存在all方法
static all(promises) {
let promisesCount = 0
let values = new Array(promises.length);
return new MyPromise((resolve, reject) => {
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(value => {
promisesCount++;
values[index] = value;
if (promisesCount === promises.length) {
resolve(values);
}
}, reason => {
reject(reason);
})
})
})
}
//MyPromise实例对象上存在race方法
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(value => {
resolve(value);
}, reason => {
reject(reason)
})
})
})
}
}
window.MyPromise = MyPromise;
})(window)
- 从零手写Promise说难也不难,但是还是花了不少时间的,希望能够帮助到像我一样想学好js,想学好Promise的朋友,一起加油吧。
最后
- 如果你想加入
特皮技术团队
,有人指导你学习,提升自己,可以公众号联系我 - 感觉对你有帮助,可以点个
在看
和赞
,转发一下,关注我们公众号:【前端巅峰
】
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。