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

Posted

技术标签:

【中文标题】async/await 在名为“then”的类方法中【英文标题】:async/await in a class method called "then" 【发布时间】:2017-04-28 22:33:14 【问题描述】:

我创建了一个具有“then”方法的类。该类与 Promise 类型无关; "then" 方法有不同的目的,并且不返回承诺。我正在尝试在 Typescript 2.1.4 中编写一个 async/await 函数来等待并返回此类的一个实例,但是 VS Code 中的 Typescript 服务器给了我错误。如果我将方法重命名为“then”以外的名称,错误就会消失。

有错误的示例代码:

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;

有人可以解释为什么不允许对具有自己的“then”方法的对象使用承诺,或者解决方法吗?

【问题讨论】:

你没有说错误是什么。这很重要。 @Carcigenicate 谢谢,我的错! 请同时发布代码。该错误似乎与您的返回类型有关。 @Carcigenicate 更新了示例代码,希望这能解决所有问题! 拥有一个并非来自承诺的.then 方法似乎有点奇怪。 【参考方案1】:

Promise 被定义为具有称为.then 的方法的对象。例如,它们没有定义为“require('bluebird/promise') 返回的模块”。

这很重要的部分原因是,当 Promise 库解析一个 Promise 时,如果该结果本身就是一个 Promise,它并不意味着在对 .then 的调用中提供最终结果。例如:

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

调用此函数并在结果上调用.then 不会返回我在doPromise2() 中得到的承诺。它会返回2 - 所以它会等到两个promise都完成,然后给出最终值。

这与我在then 中返回3 不同。它将看到结果不是一个承诺,并将其作为最终值提供。然而,问题的症结在于它如何知道这不是一个承诺。它不进行类型检查,例如 if p instanceof Promise,因为各种库中有太多的 Promise 定义和 polyfill,它们旨在协同工作。相反,他们会检查一些应如下所示的通用内容:if (typeof p.then === 'function')

该检查正在为您的班级返回 true,这会导致它认为您的值本身就是一个 Promise。它运行它,希望取回另一个 Promise 对象,但得到一个数字并失败。

【讨论】:

【参考方案2】:

您的then 方法与 Promise API 相关 - 从 javascript 鸭式的角度来看,您的类是 thenable 参见 the spec,特别是 this step

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

如果您的承诺解析为具有then 函数的对象,那么它具有特殊含义 - 它是thenable。您不能生成具有 then 函数的结果对象,并且它们没有被 Promise 解析算法处理。

【讨论】:

以上是关于async/await 在名为“then”的类方法中的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 async/await 编写 .then 函数,以便捕获来自 axios 的响应(在单独的文件和方法中,在 vue 中)

JS中的async/await的用法和理解

一起使用 async await 和 .then

Async / await vs then 哪个最适合性能?

async/await 面试题 加propmise

async await promise