浅浅手撕promise
作者:互联网
一、前言
模型压缩那块,还没琢磨明白就先不更,今天小更一下手撕promise,给小伙伴看个乐。
二、如何实现promise
知己知彼,才能百战百胜,我们先需要知道promise是什么,原理是什么,才能去实现这个过程。
1、promise是什么
说白了就是一种异步的解决方案,从语法上而言,promise就是一个对象,但这里面存放着一个未来将会执行的结果,这样可以有效解决回调地狱(俄罗斯套娃,异步套异步)。
promise一共就三种状态
pending(等待态)
,fulfiled(成功态)
,rejected(失败态)
整个过程就是,pending
状态的 Promise
对象会触发 fulfilled或者rejected
状态,在其状态处理方法resolve或者reject
方法中可以传入参数或者失败信息。当操作成功完成时,Promise 对象的 then
方法就会被调用;否则就会触发 catch
方法。
当然还有一个合并全部异步状态的Promise.all()
, 和对应的拒绝方法Promise.race
。
2、实现过程
先将整个方法搭建出来
(function name(window) {
function Promise(excutor) {
}
// 向外暴露 Promise 函数
window.Promise = Promise
})(window)
复制代码
然后往里面完善一下promise函数的逻辑,里面应该有resolve和reject
方法,并且要捕捉是否出错,出错就是reject
抛出error信息。
function Promise(excutor) {
// excutor带参,同步执行resolve和reject方法,出错就用reject抛出异常
function resolve(value) {
}
function reject(reason) {
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
复制代码
随后就是外层的then和catch方法了,then是正常执行的情况,catch就捕捉异常并上报。这里也是因为reject已经抛出异常,外层catch也自然能接受到。
Promise.prototype.then = function(onResolved, onRejected) {
}
Promise.prototype.catch = function(onRejected) {
}
复制代码
上面只是定义了函数的壳子,还需要额外调用promise下的函数,去返回对应状态的promise。
/**
* @func Promise 函数对象的 resolve()
* @param value 成功的回调函数
* @returns 返回一个指定结果 value 的成功的 Promise
*/
Promise.resolve = function(value) {
}
/**
* @func Promise 函数对象的 reject()
* @param reason 失败的回调函数
* @returns 返回一个指定结果 reject 的失败的 Promise
*/
Promise.reject = function(reason) {
}
复制代码
上述添加完整之后,基本结构已经搭建完毕,不过还有额外的多个promise合并处理的all方法和race方法。
/**
* Peomise 函数对象的 all()
* @param promises 请求数组
* @returns 返回一个 Promise
* @returns 只有 Promise 都成功时才成功,只要有一个失败就失败,并返回失败的 Promise
*/
Promise.all = function(promises) {
}
/**
* Peomise 函数对象的 race()
* @param promises 请求数组
* @returns 返回一个 Promise,其结果由第一个完成的 Promise 决定
*/
Promise.race = function(promises) {
}
复制代码
整体结构就写好了,接下来就具体完善下各个函数的逻辑,一个promise就诞生了。
下面附完整代码
/**
* 自定义 Promise 函数模块
*/
(function name(window) {
// 定义promise中的三种状态
const STATUS_PENDING = 'pending'
const STATUS_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'
function Promise(excutor) {
// excutor带参,同步执行resolve和reject方法,出错就用reject抛出异常
// 初始化该class中的初始状态
this.status = STATUS_PENDING
// 定义class中成功(value)和失败(err)时的变量值
this.value = ''
this.err = ''
// promis异步中最重要的异步,定义成功和错误函数存储的数组,存放异步时还没有执行的操作
this.onResCallbacks = []
this.onErrCallbacks = []
function resolve(value) {
// 首先判断该class中的状态,只有状态为pending时才能转化class转态为fulfilled或者rejected
if (this.status === STATUS_PENDING) {
// 修改class的转态为fulfilled,也就表示不会转进行其他转态的转化了
this.status = STATUS_FULFILLED
// 将成功(resolve)状态下的值赋给class的成功返回res
this.value = value
// 此时状态由pending转为fulfilled,执行之前在then中存放的需要执行的异步操作,promise的then中参数res接受结果
this.onResCallbacks.forEach((fn) => {
fn()
})
}
}
function reject(reason) {
// 首先判断该class中的状态,只有状态为pending时才能转化class转态为fulfilled或者rejected
if (this.status === STATUS_PENDING) {
// 修改class的转态为rejected,也就表示不会转进行其他转态的转化了
this.status = STATUS_REJECTED
// 将失败(reject)状态下的值赋给class的失败返回err
this.err = reason
// 此时状态由pending转为rejected,执行之前在catch中存放的需要执行的异步操作,promise的catch中参数err接受结果
this.onErrCallbacks.forEach((fn) => {
fn()
})
}
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function(onResolved, onRejected) {
// 如果是异步的,此时在constructor中status的状态还没变成fulfilled,所以会跳过onRes调用,没有返回
if (this.status === STATUS_FULFILLED) {
onResolved(this.res)
}
// 但是我们将此时的异步放入数组存放
if (this.status === STATUS_PENDING) {
this.onResCallbacks.push(() => onResolved(this.res))
}
// 这步操作保证了then和catch能够在同级一起"."调起,当then上述操作完后,返回class实例,便可以接在后面继续调用catch
return this
}
Promise.prototype.catch = function(onRejected) {
// 如果是异步的,此时在constructor中status的状态还没变成rejected,所以会跳过onErr调用,没有返回
if (this.status === STATUS_REJECTED) {
onRejected(this.err)
}
// 但是我们将此时的异步放入数组存放
if (this.status === STATUS_PENDING) {
this.onErrCallbacks.push(() => onRejected(this.err))
}
// 这步操作保证了then和catch能够在同级一起"."调起,当catch上述操作完后,返回class实例,便可以接在后面继续调用then
return this
}
/**
* @func Promise 函数对象的 resolve()
* @param value 成功的回调函数
* @returns 返回一个指定结果 value 的成功的 Promise
*/
Promise.resolve = function(value) {
if (value instanceof Promise) return value
return new Promise(resolve => resolve(value))
}
/**
* @func Promise 函数对象的 reject()
* @param reason 失败的回调函数
* @returns 返回一个指定结果 reject 的失败的 Promise
*/
Promise.reject = function(reason) {
if (reason instanceof Promise) return reason
return new Promise(reject => (reason))
}
/**
* Peomise 函数对象的 all()
* @param promises 请求数组
* @returns 返回一个 Promise
* @returns 只有 Promise 都成功时才成功,只要有一个失败就失败,并返回失败的 Promise
*/
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
const arr = []
let index = 0 // 解决多个异步的并发问题,要使用计数器
function promiseAdd(key, value) {
arr[key] = value
if (++index === promises.length) {
resolve(arr)
}
}
for (let i = 0; i < promises.length; i++) {
const current = promises[i]
if (current instanceof Promise) {
current.then((data) => {
promiseAdd(i, data)
}, reject)
} else {
promiseAdd(i, current)
}
}
})
}
/**
* Peomise 函数对象的 race()
* @param promises 请求数组
* @returns 返回一个 Promise,其结果由第一个完成的 Promise 决定
*/
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (const value of promises) {
this.resolve(value).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
// 向外暴露 Promise 函数
window.Promise = Promise
})(window)
复制代码
ps: 简单整理了一下,如有错误还请指正。
作者:地霊殿__三無
链接:https://juejin.cn/post/7128847180026085389
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
标签:function,resolve,浅浅,value,Promise,reject,promise 来源: https://www.cnblogs.com/Earth-Hall-Sanwu/p/16673012.html