繁体   English   中英

使等待返回可等待的,或者无限等待等待的递归

[英]Make await return thenable, or infinite recursion in awaiting awaitable

尝试提出API,并混入诸如Promise功能:

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成为新创建的可行实例。

thennull存根会使等待的结果不完整。

我不知道这是否有可能,似乎存在一些概念上的障碍,我无法全神贯注。

诺言(或任何可能的话)实现自己是没有意义的。 如果已经有了对象,则无需等待。

兑现诺言确实会自动解包ableables ,这将在您自己解决的情况下产生无限递归,并且您可以(不幸地)避免这种情况 因此,不要尝试这样做。 完全不履行您的诺言( 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);

正确的解决方案

Symbol.thenable提案。

 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检测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必须增强启发式才能巩固-这需要某种静态分析向导。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM