Promise/A + specification
Promise/A+ is A standard specification about JS Promise, ES6 Promise is actually A superset of this specification, understand this specification can help you better understand ES6 Promise
The original specification
My Chinese-English translation
The implementation code
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function PromiseDLL(fn) {
this.state = PENDING
this.value = null
this.reason = null
this.onFulfilled = null
this.onRejected = null
try {
fn(this.resolve, this.reject)
} catch (err) {
this.reject(err)
}
}
PromiseDLL.prototype.resolve = function (value) {
if (this.state ! == PENDING) {return
}
this.onFulfilled && this.onFulfilled(this.value)
this.value = value
this.state = FULFILLED
}
PromiseDLL.prototype.reject = function (reason) {
if (this.state ! == PENDING) {return
}
this.onRejected && this.onRejected(this.value)
this.reason = reason
this.state = REJECTED
}
PromiseDLL.prototype.then = function (onFulfilled, onRejected) {
const that = this
return new Promise((resolve, reject) = > {
function resolveP(x) {
if (x === this) {
throw TypeError('cannot be same object')}else {
const then = x.then
if ((typeof x === 'object' || typeof x === 'function') && typeof then === 'function') {
then.call(x, resolve, reject)
} else {
resolve(x)
}
}
}
function fulfillHandler(value) {
if (typeof onFulfilled === 'function') {
resolveP(onFulfilled(value))
} else {
resolve(value)
}
}
function rejectHandler(reason) {
if (typeof onRejected === 'function') {
resolveP(onRejected(reason))
} else {
reject(reason)
}
}
switch (this.state) {
case PENDING:
that.onFulfilled = fulfillHandler
that.onRejected = rejectHandler
break
case FULFILLED:
setTimeout(() = > {
fulfillHandler(that.value)
}, 0)
break
case REJECTED:
setTimeout(() = > {
rejectHandler(this.reason)
}, 0)
break
default:
throw TypeError('undefined promise state')}}}Copy the code
Some Bulls**t
I am more progress in the implementation of the process, the test case also again all after (secretly happy), probably because of just A few days ago already in the process of translation and bilingual writing reading through A number of times the original Promise/A + specification, but only to put an article code is A little dry, or say A jaw rabbah satisfied, So here are some thoughts on the implementation:
- Some of the rules in the specification that are broken down into multiple chapters are actually linked back and forth, such as for
onFulfilled/onRejected
Throw error related description, found in the implementationtry { fn(this.resolve, this.reject) } catch (err) { this.reject(err) } Copy the code
This code already covers various throw handling rules, so there is no need to implement it again
then/resolve/reject
Method to do additional exception handling, which also showsPromise/A+
The specification itself is very elegant - The Promise/A+ specification is deprecated
promise2 = promise1.then(...)
In thepromise2 ! == promise1
Requirements (seeOmissions – 1.3 -), here is the implementationthen
Method thought about returning directlythis
To avoid creating new ones too oftenPromise
Example, but did not continue to think about half, if there is time to think clearly about this part later and then make up then
Methods can be implemented through macro tasks or microtasks (Promise/A+)Note 3.1Explicitly not required here), used heresetTimeout
To meet theRules 2.2.4, but if you want to implement it based on microtasks, you can consider using other methods (Here I have a hunch that I can write another piece of crap about macro tasks and micro tasks)
Test Promise/A +
The Promise/A+ organization provides an official test case and uses it in A simple way. Here, we use the adapters provided by the Promise/A+ organization to test the adapters. The code is as follows
// Adapter
PromiseDLL.deferred = () = > {
const res = {}
res.promise = new Promise((resolve, reject) = > {
Object.assign(res, { resolve, reject })
})
return res
}
module.exports = PromiseDLL
Copy the code
// package.json{..."scripts": {..."test": "promises-aplus-tests promise-aplus". },... }Copy the code
All 872 test cases passed