14

对于我构建的一些 Typescript 方法,我通常需要 promise 的异步性,但我不需要 promise 返回值(从概念上讲)。一个简单的例子可能是调用 initLanguageStrings() 方法来加载应用程序使用的语言字符串。语言字符串被放置到一个全局结构中,但仍需要承诺以确保应用程序在加载语言字符串之前不会继续运行。

将此场景重复两到三遍,然后我将所有初始化工作绑定到一组承诺中,这些承诺必须在继续之前全部完成。因此,我使用 Promise.all,就像这样(示例):

initialiseApp( ): Promise< void >
{
    let promises: Promise< any >[ ] = [ ];

    promises.push( this.initLanguageStrings( ) );
    promises.push( this.initModelData( ) );
    promises.push( this.initUserInfo( ) );

    return Promise.all( promises );
}

上面的代码实际上不会编译(TS1.5/1.6),因为 Promise.all() 返回 Promise<any[]> 而不是 Promise<void>。

所以我最终写的是这样的:

return new Promise( ( resolve, reject ) => {
   Promise.all( promises )
      .then( ( dummy: any[ ] ) => {
         resolve( );
      } );         
} );

我相信这在语义上是正确的方法,因为“实现”实际上仍然是隐藏的,并且“内部承诺”(来自 Promise.all)永远不会“逃逸”给 initialiseApp() 的调用者。

但另一方面,我觉得这种方法很难看,并且想找到一种更好的方法来做到这一点,因为返回 Promise< void > 对我来说已经成为一种很常见的模式。

有没有更好的方法来实现我想要做的事情?

编译器将允许:

return Promise.all( promises ).then( ( ) => { } );

但它也让我觉得“棘手”和丑陋。

4

1 回答 1

12

因为返回 Promise< void > 对我来说已经成为一种很常见的模式

您可以使用类型断言

initialiseApp( ): Promise< void >
{
    let promises: Promise< any >[ ] = [ ];

    promises.push( this.initLanguageStrings( ) );
    promises.push( this.initModelData( ) );
    promises.push( this.initUserInfo( ) );

    return Promise.all( promises ) as Promise<void>;
}

注意:在这种情况下,当您使用断言时,您实际上是在对编译器撒谎。小心编译器认为一件事而运行时看到另一件事的错误。

return Promise.all( promises ).then( ( ) => { } );

这是正确的做法。运行时编译器推断的内容相匹配。如果你想要一个Promise<void>...然后做一个Promise<void>这就是这个代码示例所做的。

于 2015-10-06T03:36:05.657 回答