本文参考了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+。