Как изменить тип результата обещания ‹› в TypeScript

Для некоторых методов Typescript, которые я создаю, мне часто нужна асинхронность обещания, но я не требую, чтобы обещание возвращало значение (концептуально). Простым примером может быть вызов метода 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 []> not Promise‹ void>.

В итоге я пишу следующее:

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

Я считаю, что это семантически правильный подход, потому что «реализация» на самом деле остается скрытой, а «внутреннее обещание» (из Promise.all) никогда не «ускользает» от вызывающей стороны initialiseApp ().

Но, с другой стороны, я считаю этот подход уродливым и хотел бы найти более удобный способ сделать это, поскольку возвращение Promise ‹void> становится для меня довольно распространенным шаблоном.

Есть ли лучший способ достичь того, что я пытаюсь сделать?

Компилятор разрешит:

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

Но мне это тоже кажется "хитрым" и уродливым.


person Kevmeister68    schedule 06.10.2015    source источник


Ответы (1)


так как возвращение 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>, что и делает этот пример кода.

person basarat    schedule 06.10.2015
comment
Обратной стороной использования приведения (утверждения типа) является то, что мы не только лжем компилятору, но и результат перетекает из функции в вызывающую программу. Другими словами, вызывающий initialiseApp фактически получит any [] от Promise.all, даже если метод говорит, что ничего не должно возвращаться. - person Kevmeister68; 06.10.2015