尝试提出API,并混合诸如以下的诺言功能:
class Awaitable {
constructor () {
this.promise = Promise.resolve()
}
then (fn) {
// awaited result must be _this_ instance
return this.promise.then(() => fn(this))
}
}
let smth = await (new Awaitable())
console.log(smth)
此代码创建递归。
要点是让smth
是新创建的然后可用的实例。
用then
插入null
会使等待的结果不完整。
我想知道这是否完全有可能,似乎存在一些概念上的障碍,我无法全神贯注。
答案 0 :(得分:0)
一个诺言(或任何可能的话)实现自己是没有意义的。如果您已经有了对象,则无需等待。
Resolving a promise does automatically unwrap thenables,这将在您自行解决的情况下创建无限递归,而您can (unfortunately) not avoid that。因此,不要尝试这样做。完全不履行承诺(undefined
。
class Awaitable {
constructor () {
this.promise = Promise.resolve(undefined); // simplified
}
then(onfulfill, onreject) {
return this.promise.then(onfulfill, onreject);
}
// other methods
}
const smth = new Awaitable();
await smth; // works just fine now
console.log(smth);
答案 1 :(得分:0)
import { parse as parseStack } from 'stacktrace-parser'
class Awaitable {
constructor () {
this.promise = Promise.resolve()
},
[Symbol.thenable]: false,
then(fn) {
this.promise.then(() => fn(this))
return this
}
}
let smth = await (new Awaitable())
console.log(smth.then) // function
可以通过解析调用栈来确定thenable
是否调用了await
实例。这是基于stacktrace-parser软件包的解决方案:
import { parse as parseStack } from 'stacktrace-parser'
class Awaitable {
constructor () {
this.promise = Promise.resolve()
}
}
Object.defineProperty(Awaitable.prototype, 'then', {
get() {
let stack = parseStack((new Error).stack)
// naive criteria: if stacktrace is leq 3, that's async recursion, bail out
// works in webkit, FF/nodejs needs better heuristic
if (stack.length <= 3) return null
return (fn) => {
this.promise.then(() => {
fn(this)
})
return this
}
}
})
let smth = await (new Awaitable())
console.log(smth.then) // function
必须增强FF / nodejs的启发式才能巩固-这需要某种静态分析向导。