摘要:本文参考了实践教程实现这个视频,并添加了自己的一些想法。三种状态必须是函数初始状态是返回值完成时调用的方法,这里做了容错拒绝时调用的方法再次运行,正确打印出结果。
本文参考了Node.js 实践教程 - Promise 实现这个视频,并添加了自己的一些想法。
首先来看 Promise 的构造:
// 这里用 Prometheus 代替 Promise let p = new Prometheus((resolve, reject) => { resolve("hello") })
下面我们来实现它:
// 三种状态 const PENDING = Symbol() const FULFILLED = Symbol() const REJECTED = Symbol() function Prometheus (fn) { // fn 必须是函数 if (typeof fn !== "function") { throw new Error("fn must be a function!") } let state = PENDING // 初始状态是 PENDING let value = null // 返回值 function fulfill (result) { state = FULFILLED value = result } // 完成时调用的方法,这里做了容错 function resolve (result) { try { fulfill(result) } catch (err) { reject(err) } } // 拒绝时调用的方法 function reject (error) { state = REJECTED value = error } fn(resolve, reject) }
第二步,实现 then 方法:
let p = new Prometheus((resolve, reject) => { resolve("hello") }) p.then(val => { console.log(val) })
// 三种状态 const PENDING = Symbol() const FULFILLED = Symbol() const REJECTED = Symbol() function Prometheus (fn) { // fn 必须是函数 if (typeof fn !== "function") { throw new Error("fn must be a function!") } let state = PENDING // 初始状态是 PENDING let value = null // 返回值 function fulfill (result) { state = FULFILLED value = result } // 完成时调用的方法,这里做了容错 function resolve (result) { try { fulfill(result) } catch (err) { reject(err) } } // 拒绝时调用的方法 function reject (error) { state = REJECTED value = error } this.then = function (onFulfill, onReject) { switch (state) { case FULFILLED: onFulfill(value) break case REJECTED: onReject(value) break } } fn(resolve, reject) }
第三步,在 Promise 里使用异步
let p = new Prometheus((resolve, reject) => { setTimeout(() => { resolve("hello") }, 0) }) p.then(val => { console.log(val) })
直接运行上面的代码发现控制台没有打印出 hello,原因是 Prometheus 里的代码是异步执行,导致记下来执行 then 方法的时候,state 是 PENDING,后面再执行 resolve 的时候就不会走到 onFulfill 了,所以我们要在 then 方法里添加 state 为 PENDING 的分支判断,把 onFulfill 和 onReject 存到一个变量中:
// 三种状态 const PENDING = Symbol() const FULFILLED = Symbol() const REJECTED = Symbol() function Prometheus (fn) { // fn 必须是函数 if (typeof fn !== "function") { throw new Error("fn must be a function!") } let state = PENDING // 初始状态是 PENDING let value = null // 返回值 let hanler = {} function fulfill (result) { state = FULFILLED value = result handler.onFulfill(result) } // 完成时调用的方法,这里做了容错 function resolve (result) { try { fulfill(result) } catch (err) { reject(err) } } // 拒绝时调用的方法 function reject (error) { state = REJECTED value = error handler.onReject(error) } this.then = function (onFulfill, onReject) { switch (state) { case FULFILLED: onFulfill(value) break case REJECTED: onReject(value) break case PENDING: handler = { onFulfill, onReject } } } fn(resolve, reject) }
异步实现了,我们再回过头看看同步是否正常运行:
let p = new Prometheus((resolve, reject) => { resolve("hello") }) p.then(val => { console.log(val) })
发现报错信息:
TypeError: handler.onReject is not a function
因为同步执行的时候,fulfill 里 handler 是 {},所以会报错。
// 三种状态 const PENDING = Symbol() const FULFILLED = Symbol() const REJECTED = Symbol() function Prometheus (fn) { // fn 必须是函数 if (typeof fn !== "function") { throw new Error("fn must be a function!") } let state = PENDING // 初始状态是 PENDING let value = null // 返回值 let handler = {} function fulfill (result) { state = FULFILLED value = result next(handler) } // 完成时调用的方法,这里做了容错 function resolve (result) { try { fulfill(result) } catch (err) { reject(err) } } // 拒绝时调用的方法 function reject (error) { state = REJECTED value = error next(handler) } function next({ onFulfill, onReject }) { switch (state) { case FULFILLED: onFulfill && onFulfill(value) break case REJECTED: onReject && onReject(value) break case PENDING: handler = { onFulfill, onReject } } } this.then = function (onFulfill, onReject) { next({onFulfill, onReject}) } fn(resolve, reject) }
现在同步也可以正常运行了,接下来看看多个 then 链式调用:
let p = new Prometheus((resolve, reject) => { resolve("hello") }) p.then(val => { console.log(val) return "world" }).then(val => { console.log(val) })
执行代码会发现如下报错信息:
TypeError: Cannot read property "then" of undefined
原因是 then 方法没有返回 Promise。
// 三种状态 const PENDING = Symbol() const FULFILLED = Symbol() const REJECTED = Symbol() function Prometheus (fn) { // fn 必须是函数 if (typeof fn !== "function") { throw new Error("fn must be a function!") } let state = PENDING // 初始状态是 PENDING let value = null // 返回值 let handler = {} function fulfill (result) { state = FULFILLED value = result next(handler) } // 完成时调用的方法,这里做了容错 function resolve (result) { try { fulfill(result) } catch (err) { reject(err) } } // 拒绝时调用的方法 function reject (error) { state = REJECTED value = error next(handler) } function next({ onFulfill, onReject }) { switch (state) { case FULFILLED: onFulfill && onFulfill(value) break case REJECTED: onReject && onReject(value) break case PENDING: handler = { onFulfill, onReject } } } this.then = function (onFulfill, onReject) { return new Prometheus((resolve, reject) => { next({ onFulfill: val => { resolve(onFulfill(val)) }, onReject: err => { reject(onReject(err)) } }) }) } fn(resolve, reject) }
再次运行,正确打印出结果。
到此,一个非常简单的 Promise 就实现了,当然,这里其实还有很多细节没有考虑,具体还要参考 Promise/A+。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/84458.html
从零实现一个简易的 Promise 所有问题都可以通过加一层中间层来解决。 Promises/A+ 简易的,不做废话直接开始 :) const p = new Promise((resolve, reject)=>{ // 如果操作成功则调用 resolve 并传入 value // 如果操作失败则调用 reject 并传入 reason }); 通常我们都会使用上述方法获取 P...
摘要:所以,这篇文章我会带大家从零开始,手写一个基本能用的。首先,规定对象是一个构造函数,用来生成实例。然后,这个构造函数接受一个函数作为参数,该函数的两个参数分别是和。对象通过自身的状态,来控制异步操作。 刚开始写前端的时候,处理异步请求经常用callback,简单又顺手。后来写着写着就抛弃了callback,开始用promise来处理异步问题。promise写起来确实更加优美,但由于缺乏...
摘要:是什么在规范中,是一个类,它的构造函数接受一个函数。在这种情况下,是但处于状态。与一起使用关键字会暂停执行一个函数,直到等待的变成状态。此外,会一直等待调用直到下一个时序。 原文:Write Your Own Node.js Promise Library from Scratch作者:code_barbarian Promise 已经是 JavaScript 中异步处理的基石,回调...
摘要:从零开始搭建同构应用四搭建完善上一篇我们使用了的方式测试了,这篇文章来讲如何在前文的基础上搭建一个,实现真正意义上的。至此,一个简单的框架已经搭建完成,剩下的工作就是结合工作需要,在里面添砖加瓦啦。 从零开始搭建React同构应用(四):搭建Koa Server & 完善SSR 上一篇我们使用了CLI的方式测试了SSR,这篇文章来讲如何在前文的基础上搭建一个Koa Server,实现真...
阅读 3581·2020-12-03 17:42
阅读 2729·2019-08-30 15:54
阅读 2204·2019-08-30 15:44
阅读 550·2019-08-30 14:08
阅读 954·2019-08-30 14:00
阅读 1091·2019-08-30 13:46
阅读 2773·2019-08-29 18:33
阅读 2832·2019-08-29 14:11