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 中)