楼主下去看了下Promise/A+, 这是Promise实现所要遵循的标准, 看了之后模拟了一份, 目前已经打包好放在promise-polyfill上。弄懂promise不容易啊。发出来大家学习啦~
export default class Promise {
// internal method
resolvePromise(y) {
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = y
if (Array.isArray(this.nextPromises)) {
this.nextPromises.forEach((nextPromise, index) => {
const onFulfilled = this.onFulfilleds[index]
if (typeof onFulfilled === 'function') {
const y = onFulfilled(y)
Promise.Resolve(nextPromise, this.value)
this.onFulfilleds[index] = null
}
})
}
}
}
// internal method
rejectPromise(r) {
if (this.status === 'pending') {
this.status = 'rejected'
this.result = r
if (Array.isArray(this.nextPromises)) {
this.nextPromises.forEach((nextPromise, index) => {
const onRejected = this.onRejecteds[index]
if (typeof onRejected === 'function') {
const x = onRejected(r)
Promise.Resolve(nextPromise, this.result)
this.onRejecteds[index] = null
}
})
}
}
}
// internal method
static Resolve(nextPromise, x) {
if (nextPromise === x) { throw new TypeError() }
if (x instanceof Promise) {
x.then(nextPromise.resolvePromise, nextPromise.rejectPromise)
}
if (typeof x === 'object' || typeof x === 'function') {
const then = x.then
if (typeof then === 'function') {
const resolvePromise = nextPromise.resolvePromise.bind(nextPromise)
const rejectPromise = nextPromise.rejectPromise.bind(nextPromise)
try {
then.call(x, resolvePromise, rejectPromise)
} catch (e) {
nextPromise.rejectPromise(e)
}
} else {
nextPromise.resolvePromise(x)
}
} else {
nextPromise.resolvePromise(x)
}
}
constructor(executor) {
this.status = 'pending'
const resolvePromise = this.resolvePromise.bind(this)
const rejectPromise = this.rejectPromise.bind(this)
executor(resolvePromise, rejectPromise)
}
then(onFulfilled, onRejected) {
const nextPromise = new Promise((resolve, reject) => {
setTimeout(() => {
if (this.status === 'fulfilled') {
const x = onFulfilled(this.value)
Promise.Resolve(nextPromise, x)
} else if (this.status === 'rejected') {
const x = onRejected(this.result)
Promise.Resolve(nextPromise, x)
} else {
this.onFulfilleds = this.onFulfilleds || []
this.onRejecteds = this.onRejecteds || []
this.nextPromises = this.nextPromises || []
const length = this.nextPromises.length
(typeof onFulfilled === 'function') && (this.onFulfilleds[length] = onFulfilled)
(typeof onRejected === 'function') && (this.onRejecteds[length] = onRejected)
this.nextPromises.push(nextPromise)
}
}, 0)
})
return nextPromise
}
}
--------------------------之前的东东
Promise.resolve(1).then(arg => {
return new Promise(arg)
}).then(arg => console.log(arg))
这串代码没有任何输出结果,问了下gitter,说原因是new Promise(arg)是一个状态为Pending的promise对象, 会在这条链上卡主, 不会往下执行. 这让我感到有点困惑, 赶紧去翻了下MDN.MDN是这样描述then方法的.
the then method returns a Promise, you can easily chain then calls. Values returned from the onFulfilled or onRejected callback functions will be automatically wrapped in a resolved promise.
看了MDN的描述,百思不得其解. 对Promise的内部原理甚为困惑. 一个promise对象(状态是fulfilled)调用then的时候会生成一个promise对象, 这个promise对象是pending的, 会异步执行then方法的第一个回调方法, 然后Promise内部是如何包装then方法的返回值的呢?
楼主有一个假设, 用代码描述出来, 不知道是否正确....
function then(resolveHandler, rejectHandler) {
const newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
// 如果调用then方法的promise的status是rejected
if(this.status === 'rejected') {
rejectHandler(this.result)
return
}
// 不是rejected 就是fulfilled
const returnValue = resolveHandler()
// 如果returnValue不是promise类型的话
if (returnValue.___proto__ !== Promise) {
wrapPromise = Promise.resolve(returnValue) //包装返回值
wrapPromise.then(resolve)
} else {
returnValue.then(resolve, reject)
}
}, 0)
})
return newPromise
}
楼主想了之后觉得then是这样的. 大神们给出新姿势~
———————— 后更
再次一句话来说明:
Promise.prototype.then
回调里面的返回值,是通过一个变量/私有API保存的,不是return出来的,想接收/包装返回值得在Promise状态完成了之后通知执行回调函数。我再简单的举例,一个简单的异步任务如何拿到值:
promise进行一下扁平化的封装
正常返回int,string类型都是比较好处理,而返回一个Promise该如何处理呢?—— 使用回调链啊
然后我把原回答的代码再次简化了一下,当然这个代码只能大概展现then对于返回值处理的原理,真正要完成Promise还有很多的细节处理。
—————— 下面是原回答:
看了半天有点没太懂,在chrome dev跑了下代码发现你的代码报错了,导致了
new Promise
那里卡住了。然后回答你后面的困惑,
then
的Promise返回值应该进行异步包装,并且仅依靠promise的公开API是无法实现then返回的包装的,需要一层链进行包装才可以。简单的说就是:
Promise.prototype.then
中,正常的返回值,仅需要进行Promise一层包装即可,而Promise类型的返回值,则需要操作私有API进行回调链的包装,大概类似下面这样:研究过很长一段时间的Promise,所以自己也实现过一个Promise-polyfill,可以参考下实现的细节。