简体   繁体   English

async / await在一个名为“then”的类方法中

[英]async/await in a class method called “then”

I created a class that has a "then" method. 我创建了一个具有“then”方法的类。 This class is unrelated to the Promise type; 这个类与Promise类型无关; the "then" method has a different purpose and doesn't return a promise. “then”方法有不同的目的,不会返回承诺。 I am trying to write an async/await function in Typescript 2.1.4 that awaits and returns an instance of this class, but the Typescript server in VS Code is giving me errors. 我试图在Typescript 2.1.4中编写async / await函数,等待并返回此类的实例,但VS Code中的Typescript服务器给了我错误。 If I rename the method to something other than "then", the errors go away. 如果我将方法重命名为“then”以外的其他方法,则错误消失。

Example code with errors: 带错误的示例代码:

class MyClass {
    then(): number {
        // this method isn't related to Promise.then
        return 2 + 2;
    }
}

// three errors below go away when "then" is renamed

// [ts] An async function or method must have a valid awaitable return type.
async function my_async(): Promise<MyClass> {
    let a: Promise<MyClass> = Promise.resolve(new MyClass());

    // [ts] Operand for 'await' does not have a valid callable 'then' member.
    let b: MyClass = await a;

    // [ts] Return expression in async function does not have a valid callable 'then' member.
    return b;
}

Can someone explain why using promises with an object that has its own "then" method is not allowed, or a work around? 有人可以解释为什么不允许使用具有自己的“then”方法的对象的promises,或者解决这个问题?

Promises are defined as objects that have a method called .then . Promise被定义为具有名为.then的方法的对象。 They are not defined, for instance, as "the module returned by require('bluebird/promise') ". 例如,它们没有被定义为“由require('bluebird/promise')返回的模块”。

Part of what makes this important is that when a promise library is resolving a promise, it is not meant to offer up the final result inside of a call to .then if that result is a promise itself. 使这一点变得重要的部分原因是,当一个promise库正在解析一个promise时,如果该结果是一个promise本身,那么它并不意味着在.then调用中提供最终结果。 For instance: 例如:

function myFn() {
  // doPromise1 will eventually give us `1`.
  return doPromise1().then(x => {
    // doPromise2 will eventually give us `2`.
    return doPromise2();
  });
}

Calling this function and calling .then on the result won't return the promise I got inside of doPromise2() . 调用此函数和调用.then对结果不会返回我的内部承诺doPromise2() It will return 2 - so it will wait until both promises finish, and give that final value. 它将返回2 - 所以它将等到两个promises完成,并给出最终值。

This is different from if I had returned 3 inside of then . 这是,如果我回来了不同的3then It would see that the result is not a promise, and offer up that as the final value. 它会看到结果不是承诺,并将其作为最终值提供。 However, the crux of the issue is how it knows that that is not a promise. 然而,问题的关键在于它如何知道这不是一个承诺。 It doesn't do typechecking, like if p instanceof Promise because there are too many Promise definitions and polyfills in various libraries, and they're meant to work together. 它没有做类型检查,就像if p instanceof Promise因为在各种库中有太多的Promise定义和polyfill,并且它们意味着一起工作。 Instead, they check something generic that should look like this: if (typeof p.then === 'function') . 相反,他们检查一些通用的东西应该是这样的: if (typeof p.then === 'function')

That check is returning true for your class, and this causes it to think your value is a Promise itself. 对于您的班级,该检查将返回true ,这会使其认为您的值本身就是Promise。 It runs it, hoping to get back another promise object, but gets a number and fails. 它运行它,希望得到另一个promise对象,但得到一个数字并失败。

Your then method is related to the Promise API - from the JavaScript ducktyping point of view, your class is a thenable see the spec , specifically this step then方法关系到无极API -但从JavaScript的鸭子类型来看,你的类是thenable看到规范 ,特别是这一步

...
Let then be Get(resolution, "then").
...

If your promise resolves to an object that has a then function, then it has a special meaning - it's a thenable . 如果你的诺言解析为具有then函数的对象,那么它具有特殊的意义 - 它是一个thenable You cannot yield result objects that have a then function and not have them treated by the Promise resolution algorithm. 您不能生成具有then函数的结果对象,也不能通过Promise解析算法处理它们。

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

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