共计 14055 个字符,预计需要花费 36 分钟才能阅读完成。
开发中 Promise
是及其罕用的语法,基本上对于异步的解决大都是通过 Promise
来进行实现。Promise 标准有很多,ES6 最终采纳的是Promise/A+ 标准
, 所以以下代码也根本是基于这个标准来进行编写的。
首先咱们先列举 Promise 的所有实例办法跟静态方法
实例办法
- then:
new Promise((resolve, reject) => {...}).then(() => {console.log('rsolve 胜利回调')}, () => {console.log('reject 失败回调')})
- catch:
new Promise((resolve, reject) => {...}).catch(() => {console.log('reject 失败办法')})
- finally:
new Promise((resolve, reject) => {...}).finally(() => {console.log('成功失败都进入')})
- 以上办法调用都将返回新的
Promise
静态方法
- resolve:
Promise.resolve(value)
返回Promise
实例 - reject:
Promise.reject(value)
返回Promise
实例 - all:
Promise.all(promises)
: 传入数组格局的Promise
并返回新的Promise
实例,胜利便依照程序把值返回进去,其中一个失败则间接变成失败 - race:
Promise.race(promises)
: 传入数组格局的Promise
并返回新的Promise
实例,胜利与失败取决第一个的实现形式
Promise
状态一旦确定变不可再发生变化,有以下三个状态:pending
、fulfilled
、rejected
Promise
在浏览器中的实现是放于微工作队列中的,须要做微工作的解决(JavaScript 中的 Event Loop(事件循环)机制
)
1. 申明 Promise 的实例办法
class Promise { | |
_value | |
_state = 'pending' | |
_queue = [] | |
constructor(fn) {if (typeof fn !== 'function') {throw 'Promise resolver undefined is not a function'} | |
/* | |
new Promise((resolve, reject) => { | |
resolve: 胜利 | |
reject: 失败 | |
}) | |
*/ | |
fn(this._resolve.bind(this), this._reject.bind(this)) | |
} | |
// 接管 1 - 2 参数,第一个为胜利的回调,第二个为失败的回调 | |
then(onFulfilled, onRejected) { | |
// 有可能曾经 resolve 了,因为 Promise 能够提前 resolve, 而后 then 办法前面注册 | |
if (this._state === 'fulfilled') {onFulfilled?.(this._value) | |
return | |
} | |
// reject 同理 | |
if (this._state === 'rejected') {onRejected?.(this._value) | |
return | |
} | |
// Promise 还没有实现,push 到一个队列,到时候实现的时候,执行这个队列外面对应的函数 | |
this._queue.push({ | |
onFulfilled, | |
onRejected, | |
}) | |
} | |
// 接管失败的回调 | |
catch(onRejected) { | |
// 相当于间接调用 then 传入失败的回调 | |
this.then(null, onRejected) | |
} | |
// 胜利与失败都执行的回调 | |
finally(onDone) {const fn = () => onDone() | |
this.then(fn, fn) | |
} | |
// 胜利 resolve | |
_resolve(value) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
this._state = 'fulfilled' | |
// 把值存起来,当再次调用的时候间接取这个值就行,因为 Promise 一旦确定就不会产生扭转了 | |
this._value = value | |
// 执行后面.then 办法外面 push 函数模式的参数,这样就执行对应的办法了。this._queue.forEach((callback) => {callback.onFulfilled?.(this._value) | |
}) | |
} | |
// 失败 reject | |
_reject(error) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
this._state = 'rejected' | |
this._value = error | |
this._queue.forEach((callback) => {callback.onRejected?.(this._value) | |
}) | |
} | |
} |
调用逻辑:
- 通过
then
办法传入函数模式的参数,也就是onFulfilled
=>then((onFulfilled, onRejected) => {...})
- 在
then
办法中把onFulfilled
函数放入_queue
这个汇合中。=>this._queue.push({onFulfilled, onRejected})
- 等异步回调实现,执行
resolve
函数,这个时候就调用_queue
收集好的通过then
办法注册的函数。对立执行这些函数,这样就达到异步回调实现,执行对应的then
办法外面的函数
// 后果打印 | |
const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('success') | |
}, 1000) | |
}) | |
p.then((res) => {console.log(res) // => success | |
}) | |
// reject | |
const p1 = new Promise((resolve, reject) => {setTimeout(() => {reject('fail') | |
}, 1000) | |
}) | |
p1.catch((res) => {console.log(res) // => fail | |
}) | |
// finally | |
const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve() | |
}, 1000) | |
}) | |
p2.finally(() => {console.log('done') // => done | |
}) |
在线代码演示
2. 微工作解决以及返回 Promise
a. 进行微工作解决
在浏览器中 Promise
实现之后会被推入微工作,所以咱们也须要进行这块的解决。浏览器中应用 MutationObserver,node 能够应用process.nextTick
class Promise { | |
... | |
// 推入微工作 | |
_nextTick(fn) {if (typeof MutationObserver !== 'undefined') { // 浏览器通过 MutationObserver 实现微工作的成果 | |
// 这块能够独自拿进去共用,防止不必要的开销,不然每次都须要生成节点。const observer = new MutationObserver(fn) | |
let count = 1 | |
const textNode = document.createTextNode(String(count)) | |
observer.observe(textNode, {characterData: true}) | |
textNode.data = String(++count) | |
} else if (typeof process.nextTick !== 'undefined') { // node 端通过 process.nextTick 来实现 | |
process.nextTick(fn) | |
} else {setTimeout(fn, 0) | |
} | |
} | |
// 胜利 resolve | |
_resolve(value) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
// 推入微工作 | |
this._nextTick(() => { | |
this._state = 'fulfilled' | |
this._value = value | |
this._queue.forEach((callback) => {callback.onFulfilled?.(this._value) | |
}) | |
}) | |
} | |
// 失败 reject | |
_reject(error) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
// 推入微工作 | |
this._nextTick(() => { | |
this._state = 'rejected' | |
this._value = error | |
this._queue.forEach((callback) => {callback.onRejected?.(this._value) | |
}) | |
}) | |
} | |
... | |
} |
成果演示
b. 返回 Promise 进行链式调用
通常 Promise
会解决多个异步申请,有时候申请之间是有相互依赖关系的。
例如:
const getUser = () => {return new Promise((resolve, reject) => {setTimeout(() => { | |
resolve({userId: '123'}) | |
}, 500) | |
}) | |
} | |
const getDataByUser = (userId) => {return new Promise((resolve, reject) => {setTimeout(() => { | |
// .... | |
resolve({a: 1}) | |
}, 500) | |
}) | |
} | |
// 应用 | |
getUser().then((user) => {return getDataByUser(user.userId) | |
}).then((res) => {console.log(res)// {a: 1} | |
}) |
getDataByUser
依赖 getUser
申请回来的用户信息,这里就须要用到 Promise
链式的调用, 上面咱们来改变咱们的代码
class Promise {constructor(fn) {fn(this._resolve.bind(this), this._reject.bind(this)) | |
} | |
... | |
// 1. 这时候 then 办法须要返回新的 Promise 了, 因为须要进行链式调用,并且下一个 then 办法承受上一个 then 办法的值 | |
// 2. 返回的 Promise 必定是一个新的 Promise,不然就会共用状态跟返回后果了。// 3. 把上一个 then 办法中的返回值当做下一个 Promise resolve 的值 | |
then(onFulfilled, onRejected) { | |
// 返回新的 Promise | |
return new Promise((resolve, reject) => { | |
// 有可能曾经 resolve 了,因为 Promise 能够提前 resolve, 而后 then 办法前面注册, 这个时候能够间接把值返给函数就好了 | |
if (this._state === 'fulfilled' && onFulfilled) {this._nextTick(onFulfilled.bind(this, this._value)) | |
return | |
} | |
if (this._state === 'rejected' && onRejected) {this._nextTick(onRejected.bind(this, this._value)) | |
return | |
} | |
/* | |
把以后 Promise 的 then 办法的参数跟新的 Promise 的 resolve, reject 存到一起,以此来做关联。这样就能把上一个 Promise 中的 onFulfilled 与新的 Promise 中的 resolve 两个关联到一块,而后便能够做赋值之类的操作了。reject 同理 | |
*/ | |
this._queue.push({ | |
onFulfilled, | |
onRejected, | |
resolve, | |
reject | |
}) | |
}) | |
} | |
// reject 同理 | |
_resolve(value) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
// 下面示例外面其实返回的是一个 Promise, 而不是间接返回的值,所以,这里咱们须要做一个非凡解决。// 就是 resolve()的值如果是 Promise 的对象,咱们须要解析 Promise 的后果,而后在把值传给 resolve | |
if (typeof value === 'object' && typeof value.then === 'function') { | |
// 咱们能够把以后_resolve 办法传递上来,因为 then 办法中的参数,一经下个 Promise resolve, 便会执行 then 办法对应的参数,而后把对应的值传入。// 这样就能取到 Promise 中的值 | |
// this._resove => obj.onFulfilled?.(this._value) | |
// this._reject => obj.onRejected?.(this._value) | |
value.then(this._resolve.bind(this), this._reject.bind(this)) | |
return | |
} | |
// 推入微工作 | |
this._nextTick(() => { | |
this._state = 'fulfilled' | |
this._value = value | |
this._queue.forEach((obj) => { | |
// 承受 onFulfilled 返回值 | |
const val = obj.onFulfilled?.(this._value) | |
// reoslve 这个值, 此时 onFulfilled 是以后 Promise then 办法中的第一个参数:Promise.then((res) => {consolle.log(res)}) | |
// obj.resolve 是新的 Promise 的 resolve 函数,这样就把 then 办法中的返回值传给下一个 Promise | |
obj.resolve(val) | |
}) | |
}) | |
} | |
... | |
} |
成果演示
调用逻辑:
- 微工作采纳
MutationObserver
跟process.nextTick
来进行实现 Promise
链式调用,这里通过把then
办法中的(onFulfilled, onRejected)
参数与新返回的Promise
中的(resolve, reject)
关联到一起。- 一旦上一个
Promise
胜利, 调用onFulfilled
函数,就能够把onFulfilled
中返回的值,放到新的 Promise 的 resolve 中。 - 如果遇到
resolve
的值是Promise
对象,递归进行解析,而后再把值返回进来
残缺代码
class Promise { | |
_value | |
_state = 'pending' | |
_queue = [] | |
constructor(fn) {if (typeof fn !== 'function') {throw new Error('Promise resolver undefined is not a function') | |
} | |
/* | |
new Promise((resolve, reject) => { | |
resolve: 胜利 | |
reject: 失败 | |
}) | |
*/ | |
fn(this._resolve.bind(this), this._reject.bind(this)) | |
} | |
// 接管 1 - 2 参数,第一个为胜利的回调,第二个为失败的回调 | |
then(onFulfilled, onRejected) { | |
// 返回新的 Promise | |
return new Promise((resolve, reject) => { | |
// 有可能曾经 resolve 了,因为 Promise 能够提前 resolve, 而后 then 办法前面注册, 这个时候能够间接把值返给函数就好了 | |
if (this._state === 'fulfilled' && onFulfilled) {this._nextTick(onFulfilled.bind(this, this._value)) | |
return | |
} | |
if (this._state === 'rejected' && onRejected) {this._nextTick(onRejected.bind(this, this._value)) | |
return | |
} | |
// 把以后 Promise 的 then 办法的参数跟新的 Promise 的 resolve, reject 存到一起,以此来做关联 | |
this._queue.push({ | |
onFulfilled, | |
onRejected, | |
resolve, | |
reject | |
}) | |
}) | |
} | |
// 接管失败的回调 | |
catch(onRejected) {return this.then(null, onRejected) | |
} | |
// 胜利与失败都执行的回调 | |
finally(onDone) {return this.then((value) => {onDone() | |
return value | |
}, (value) => {// console.log(value) | |
onDone() | |
throw value | |
}) | |
} | |
// 推入微工作 | |
_nextTick(fn) {if (typeof MutationObserver !== 'undefined') { // 浏览器 | |
// 这块能够独自拿进去共用,防止不必要的开销,不然每次都须要生成节点。const observer = new MutationObserver(fn) | |
let count = 1 | |
const textNode = document.createTextNode(String(count)) | |
observer.observe(textNode, {characterData: true}) | |
textNode.data = String(++count) | |
} else if (typeof process.nextTick !== 'undefined') { // node | |
process.nextTick(fn) | |
} else {setTimeout(fn, 0) | |
} | |
} | |
// 胜利 resolve | |
_resolve(value) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
// 下面示例外面其实返回的是一个 Promise, 而不是间接返回的值,所以,这里咱们须要做一个非凡解决。// 就是如果 resolve()的如果是 Promise 的对象,咱们须要解析 Promise 的后果,而后在把值传给 resolve | |
if (typeof value === 'object' && typeof value.then === 'function') { | |
// 咱们能够把以后_resolve 办法传递上来,因为 then 办法中的参数,一经下个 Promise resolve, 便会执行 then 办法对应的参数,而后把对应的值传入。// 这样就能取到 Promise 中的值 | |
// this._resove => obj.onFulfilled?.(this._value) | |
// this._reject => obj.onRejected?.(this._value) | |
value.then(this._resolve.bind(this), this._reject.bind(this)) | |
return | |
} | |
// 推入微工作 | |
this._nextTick(() => { | |
this._state = 'fulfilled' | |
this._value = value | |
this._queue.forEach((obj) => { | |
// 应用 try catch 来捕捉 onFulfilled 存在函数外部谬误的状况 | |
try { | |
// 承受 onFulfilled 返回值,如果不存在,把 this._value 往下传递 | |
const val = obj.onFulfilled ? obj.onFulfilled(this._value) : this._value | |
// reoslve 这个值, 此时 onFulfilled 是以后 Promise then 办法中的第一个参数:Promise.then((res) => {consolle.log(res)}) | |
// obj.resolve 是新的 Promise 的 resolve 函数,这样就把 then 办法中的返回值传给下一个 Promise | |
obj.resolve(val) | |
} catch (e) {obj.reject(e) | |
} | |
}) | |
}) | |
} | |
// 失败 reject | |
_reject(error) {if (this._state !== 'pending') return | |
this._nextTick(() => { | |
this._state = 'rejected' | |
this._value = error | |
this._queue.forEach((obj) => { | |
try {const val = obj.onRejected ? obj.onRejected(this._value) : this._value | |
// 以后 reject 执行结束之后,会返回新的 Promise,应该是能失常 resolve 的,所以这里要用 resolve, 不应该持续应用 reject 来让下个 Promise 执行失败流程 | |
obj.resolve(val) | |
} catch (e) {obj.reject(e) | |
} | |
}) | |
}) | |
} | |
} |
申明 Promise 的静态方法
总共有 4 个静态方法: Promise.resolve
、Promise.reject
、Promise.all
、Promise.race
,对立返回的都是新的 Promise。
class Promise { | |
... | |
/** | |
* 间接 resolve | |
*/ | |
static resolve(value) { | |
// 是 Promise 间接返回 | |
if (value instanceof Promise) {return value} else if (typeof value === 'object' && typeof value.then === 'function') { | |
// 传入的对象含有 then 办法 | |
const then = value.then | |
return new Promise((resolve) => {then.call(value, resolve) | |
}) | |
} else { | |
// 失常返回值,间接返回新的 Promise 在 resolve 这个值 | |
return new Promise((resolve) => resolve(value)) | |
} | |
} | |
/** | |
* 间接 reject, 测试下 Promise.reject 并没做非凡解决,所以间接返回即可。*/ | |
static reject(value) {return new Promise((resolve, reject) => reject(value)) | |
} | |
/** | |
* 传入数组格局的 `Promise` 并返回新的 `Promise` 实例,胜利便依照程序把值返回进去,其中一个失败则间接变成失败 | |
*/ | |
static all(promises) {return new Promise((resolve, reject) => { | |
let count = 0 | |
let arr = [] | |
// 依照对应的下标 push 到数组外面 | |
promises.forEach((promise, index) => { | |
// 转换成 Promise 对象 | |
Promise.resolve(promise).then((res) => { | |
count++ | |
arr[index] = res | |
if (count === promises.length) {resolve(arr) | |
} | |
}, err => reject(err)) | |
}) | |
}) | |
} | |
/** | |
* 传入数组格局的 `Promise` 并返回新的 `Promise` 实例,胜利与失败取决第一个的实现形式 | |
*/ | |
static race(promises) {return new Promise((resolve, reject) => {promises.forEach((promise, index) => { | |
// 转换成 Promise 对象 | |
Promise.resolve(promise).then((res) => { | |
// 谁先执行间接 resolve, 或 reject | |
resolve(res) | |
}, err => reject(err)) | |
}) | |
}) | |
} | |
... | |
} |
Promise 实现残缺代码
class Promise { | |
_value | |
_state = 'pending' | |
_queue = [] | |
constructor(fn) {if (typeof fn !== 'function') {throw new Error('Promise resolver undefined is not a function') | |
} | |
/* | |
new Promise((resolve, reject) => { | |
resolve: 胜利 | |
reject: 失败 | |
}) | |
*/ | |
fn(this._resolve.bind(this), this._reject.bind(this)) | |
} | |
/** | |
* 接管 1 - 2 参数,第一个为胜利的回调,第二个为失败的回调 | |
* | |
* @param {*} onFulfilled | |
* @param {*} onRejected | |
* @return {*} | |
* @memberof Promise | |
*/ | |
then(onFulfilled, onRejected) { | |
// 返回新的 Promise | |
return new Promise((resolve, reject) => { | |
// 有可能曾经 resolve 了,因为 Promise 能够提前 resolve, 而后 then 办法前面注册, 这个时候能够间接把值返给函数就好了 | |
if (this._state === 'fulfilled' && onFulfilled) {this._nextTick(onFulfilled.bind(this, this._value)) | |
return | |
} | |
if (this._state === 'rejected' && onRejected) {this._nextTick(onRejected.bind(this, this._value)) | |
return | |
} | |
// 把以后 Promise 的 then 办法的参数跟新的 Promise 的 resolve, reject 存到一起,以此来做关联 | |
this._queue.push({ | |
onFulfilled, | |
onRejected, | |
resolve, | |
reject | |
}) | |
}) | |
} | |
/** | |
* 接管失败的回调 | |
* | |
* @param {*} onRejected | |
* @return {*} | |
* @memberof Promise | |
*/ | |
catch(onRejected) {return this.then(null, onRejected) | |
} | |
/** | |
* 胜利与失败都执行的回调 | |
* | |
* @param {*} onDone | |
* @return {*} | |
* @memberof Promise | |
*/ | |
finally(onDone) {return this.then((value) => {onDone() | |
return value | |
}, (value) => {onDone() | |
// 间接报错,能够在 try catch 中捕捉谬误 | |
throw value | |
}) | |
} | |
/** | |
* 间接 resolve | |
* | |
* @static | |
* @param {*} value | |
* @return {*} | |
* @memberof Promise | |
*/ | |
static resolve(value) {if (value instanceof Promise) {return value} else if (typeof value === 'object' && typeof value.then === 'function') { | |
// 传入的对象含有 then 办法 | |
const then = value.then | |
return new Promise((resolve) => {then.call(value, resolve) | |
}) | |
} else {return new Promise((resolve) => resolve(value)) | |
} | |
} | |
/** | |
* 间接 reject, 测试下 reject 在 Promise.reject 中没做非凡解决 | |
* | |
* @static | |
* @param {*} value | |
* @return {*} | |
* @memberof Promise | |
*/ | |
static reject(value) {return new Promise((resolve, reject) => reject(value)) | |
} | |
/** | |
* 传入数组格局的 `Promise` 并返回新的 `Promise` 实例,胜利便依照程序把值返回进去,其中一个失败则间接变成失败 | |
* | |
* @static | |
* @param {*} promises | |
* @memberof Promise | |
*/ | |
static all(promises) {return new Promise((resolve, reject) => { | |
let count = 0 | |
let arr = [] | |
if (Array.isArray(promises)) {if (promises.length === 0) {return resolve(promises) | |
} | |
promises.forEach((promise, index) => { | |
// 转换成 Promise 对象 | |
Promise.resolve(promise).then((res) => { | |
count++ | |
arr[index] = res | |
if (count === promises.length) {resolve(arr) | |
} | |
}, err => reject(err)) | |
}) | |
return | |
} else {reject(`${promises} is not Array`) | |
} | |
}) | |
} | |
/** | |
* 传入数组格局的 `Promise` 并返回新的 `Promise` 实例,胜利与失败取决第一个的实现形式 | |
* | |
* @static | |
* @param {*} promises | |
* @return {*} | |
* @memberof Promise | |
*/ | |
static race(promises) {return new Promise((resolve, reject) => {if (Array.isArray(promises)) {promises.forEach((promise, index) => { | |
// 转换成 Promise 对象 | |
Promise.resolve(promise).then((res) => {resolve(res) | |
}, err => reject(err)) | |
}) | |
} else {reject(`${promises} is not Array`) | |
} | |
}) | |
} | |
// 推入微工作 | |
_nextTick(fn) {if (typeof MutationObserver !== 'undefined') { // 浏览器 | |
// 这块能够独自拿进去共用,防止不必要的开销,不然每次都须要生成节点。const observer = new MutationObserver(fn) | |
let count = 1 | |
const textNode = document.createTextNode(String(count)) | |
observer.observe(textNode, {characterData: true}) | |
textNode.data = String(++count) | |
} else if (typeof process.nextTick !== 'undefined') { // node | |
process.nextTick(fn) | |
} else {setTimeout(fn, 0) | |
} | |
} | |
// 胜利 resolve | |
_resolve(value) { | |
// 状态确定了,就不再发生变化了 | |
if (this._state !== 'pending') return | |
// 下面示例外面其实返回的是一个 Promise, 而不是间接返回的值,所以,这里咱们须要做一个非凡解决。// 就是如果 resolve()的如果是 Promise 的对象,咱们须要解析 Promise 的后果,而后在把值传给 resolve | |
if (typeof value === 'object' && typeof value.then === 'function') { | |
// 咱们能够把以后_resolve 办法传递上来,因为 then 办法中的参数,一经下个 Promise resolve, 便会执行 then 办法对应的参数,而后把对应的值传入。// 这样就能取到 Promise 中的值 | |
// this._resove => obj.onFulfilled?.(this._value) | |
// this._reject => obj.onRejected?.(this._value) | |
value.then(this._resolve.bind(this), this._reject.bind(this)) | |
return | |
} | |
// 通过打印测试,如果间接在线程里进行 resolve, 状态跟值如同是间接就扭转了,并没有执行完主流程,在执行微工作的时候进行批改的。// 所以把状态扭转和值的批改移出了微工作,只有在走回调的时候才通过微工作进行解决 | |
this._state = 'fulfilled' | |
this._value = value | |
// 推入微工作 | |
this._nextTick(() => {this._queue.forEach((obj) => { | |
// 应用 try catch 来捕捉 onFulfilled 存在函数外部谬误的状况 | |
try { | |
// 承受 onFulfilled 返回值,如果不存在,把 this._value 往下传递 | |
const val = obj.onFulfilled ? obj.onFulfilled(this._value) : this._value | |
// reoslve 这个值, 此时 onFulfilled 是以后 Promise then 办法中的第一个参数:Promise.then((res) => {consolle.log(res)}) | |
// obj.resolve 是新的 Promise 的 resolve 函数,这样就把 then 办法中的返回值传给下一个 Promise | |
obj.resolve(val) | |
} catch (e) {obj.reject(e) | |
} | |
}) | |
}) | |
} | |
// 失败 reject | |
_reject(error) {if (this._state !== 'pending') return | |
this._state = 'rejected' | |
this._value = error | |
this._nextTick(() => {this._queue.forEach((obj) => { | |
try { | |
// 用户传入的函数外部谬误捕捉 | |
if (obj.onRejected) {const val = obj.onRejected(this._value) | |
// 以后 reject 执行结束之后,会返回新的 Promise,应该是能失常 resolve 的,所以这里要用 resolve, 不应该持续应用 reject 来让下个 Promise 执行失败流程 | |
obj.resolve(val) | |
} else { | |
// 递归传递 reject 谬误 | |
obj.reject(this._value) | |
} | |
} catch (e) {obj.reject(e) | |
} | |
}) | |
}) | |
} | |
} |
残缺演示成果
博客原文地址
本我的项目残缺代码:GitHub
以上就是 Promise 的实现计划, 当然这个跟残缺的 Promises/A+ 标准
是有区别的。这里只是用做于学习之用。
QQ 群 | 公众号 |
---|---|
前端打杂群 |
冬瓜书屋 |
我本人新创建了一个互相学习的群,无论你是筹备入坑的小白,还是半路入行的同学,心愿咱们能一起分享与交换。
QQ 群:810018802, 点击退出