从零手写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的敌人,一起加油吧。
最初
- 如果你想退出
特皮技术团队
,有人领导你学习,晋升本人,能够公众号分割我 - 感觉对你有帮忙,能够点个
在看
和赞
,转发一下,关注咱们公众号:【前端巅峰
】