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

时间:2019-09-10 21:28:43

标签: javascript promise async-await es6-promise ecmascript-2017

尝试提出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会使等待的结果不完整。

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

2 个答案:

答案 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)

正确的解决方案

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

易碎的non-standard解决方案

可以通过解析调用栈来确定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的启发式才能巩固-这需要某种静态分析向导。