共计 13071 个字符,预计需要花费 33 分钟才能阅读完成。
从零手写 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.then
Promise.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 的敌人,一起加油吧。
最初
- 如果你想退出
特皮技术团队
,有人领导你学习,晋升本人,能够公众号分割我 - 感觉对你有帮忙,能够点个
在看
和赞
,转发一下,关注咱们公众号:【前端巅峰
】
正文完
发表至: javascript
2020-08-20