普通函数和异步函数返回的Promise类型有区别吗?

时间:2017-09-26 22:09:27

标签: typescript promise async-await q

假设我有一个带有以下(最新)软件包的Typescript项目:

  • q@1.5.0
  • typescript@2.5.2
  • @类型/ Q @ 1.0.5

现在让我们说在我的项目中我定义了一个返回Promise的函数(由Typescript的原生环境声明定义):

import * as q from "q";

function doSomethingElseAsync(): Promise<number> {
    return q.Promise<number>((resolve, reject) => {
        setTimeout(() => resolve(1), 5000);
    });
}

编译时,Typescript会抱怨以下错误:

error TS2322: Type 'Q.Promise<number>' is not assignable to type 'Promise<number>'.
  Types of property 'then' are incompatible.
    Type '<U>(onFulfill?: ((value: number) => IWhenable<U>) | undefined, onReject?: ((error: any) => IWhena...' is not assignable to type '<TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TR...'.
      Types of parameters 'onFulfill' and 'onfulfilled' are incompatible.
        Type '((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined' is not assignable to type '((value: number) => IWhenable<TResult1 | TResult2>) | undefined'.
          Type 'null' is not assignable to type '((value: number) => IWhenable<TResult1 | TResult2>) | undefined'.

有一段时间,我认为这是因为Q Promises与Typescript的原生声明不兼容。但是,如果我将async关键字添加到函数定义中,则错误将完全消失。

我对这种行为感到很困惑。这是Typescript,Q或Q类型中的错误吗?或者这是编译器的一些深奥但预期的行为?

2 个答案:

答案 0 :(得分:0)

我的猜测是将async关键字添加到您的函数会导致Javascript将该函数的返回值包装在本机Promise中,以便函数返回一个promise或一个值,结果将是await的承诺。

例如,它会执行以下操作:

Promise.resolve().then(() => doSomethingElseAsync())

如果没有async关键字,您将返回q承诺,该承诺不是原生Promise的实例,因此您会收到类型错误。< / p>

我相信它也能正常工作(移除q):

function doSomethingElseAsync(): Promise<number> {
    return Promise<number>((resolve, reject) => {
        setTimeout(() => resolve(1), 5000);
    });
}

或者如果您的环境不包含本机Promise类,也许更改返回类型可能会起作用,如下所示:

function doSomethingElseAsync(): q.Promise<number> {
    return q.Promise<number>((resolve, reject) => {
        setTimeout(() => resolve(1), 5000);
    });
}

答案 1 :(得分:0)

看起来问题只是Q promises与async / await不兼容。

我尝试将异步功能的返回类型从原生Promise交换到q.Promise。编译器现在给我这个错误:

Type '<T>(resolver: (resolve: (val?: T | PromiseLike<T> | undefined) => void, reject: (reason?: any) =>...' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
  Type '<T>(resolver: (resolve: (val?: T | PromiseLike<T> | undefined) => void, reject: (reason?: any) =>...' provides no match for the signature 'new <T>(executor: (resolve: (value?: T | PromiseLike<T> | undefined) => void, reject: (reason?: any) => void) => void): PromiseLike<T>'.

它表示返回类型“不是ES5 / ES3中的有效异步函数返回类型,因为它不引用与Promise兼容的构造函数值。”这是有道理的,因为q.Promise不是可以使用new调用的构造函数。相比之下,其他承诺实现(如Bluebird)确实具有兼容的构造函数。

相关问题