2016-05-09 24 views
12

私はNode.jsとTypeScriptを使用していますが、async/awaitを使用しています。 これは私のテストケースである:非同期/待機のタイムアウト

async function doSomethingInSeries() { 
    const res1 = await callApi(); 
    const res2 = await persistInDB(res1); 
    const res3 = await doHeavyComputation(res1); 
    return 'simle'; 
} 

私は全体的な機能のためのタイムアウトを設定したいと思います。私。 res1が2秒かかる場合、res2は0.5秒かかります。res3は5秒かかります。3秒後にエラーが発生するようにタイムアウトしたいと思います。スコープが失われるため、通常のsetTimeoutコールで

は問題です:

async function doSomethingInSeries() { 
    const timerId = setTimeout(function() { 
     throw new Error('timeout'); 
    }); 

    const res1 = await callApi(); 
    const res2 = await persistInDB(res1); 
    const res3 = await doHeavyComputation(res1); 

    clearTimeout(timerId); 

    return 'simle'; 
} 

そして、私は通常のPromise.catchでそれをキャッチすることはできません。

doSomethingInSeries().catch(function(err) { 
    // errors in res1, res2, res3 will be catched here 
    // but the setTimeout thing is not!! 
}); 

解決する方法上の任意のアイデアを?

+0

特定の約束ライブラリを使用していますか? – Bergi

+0

いいえ、ただの約束です。 – nkint

+0

2 + 0.5 + 5 + 3は11.5秒のタイムアウトになりますか? – Bergi

答えて

19

あなたはタイムアウトを作るためにPromise.raceを使用することができます。

Promise.race([ 
    doSomethingInSeries(), 
    new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 11.5e3)) 
]).catch(function(err) { 
    // errors in res1, res2, res3 and the timeout will be caught here 
}) 

あなたは約束でそれをラップせずにsetTimeoutを使用することはできません。

+0

私は同じソリューションを、とにかくありがとう! – nkint

+0

なぜ 'clearTiimeout'は必要ないのですか? – nkint

+0

@nkint: 'doSomethingInSeries()'が最初に解決されたときに拒否が考慮されないので、クリアする必要はありません。私たちはそれをクリアすることができますが、それはむしろ複雑になるでしょう(最適には、レースはより遅い約束を取り消す方法を持っていますが、それは本来の約束では不可能です)。 – Bergi

2

[OK]を私はこの方法が見つかりました:

async function _doSomethingInSeries() { 
    const res1 = await callApi(); 
    const res2 = await persistInDB(res1); 
    const res3 = await doHeavyComputation(res1); 
    return 'simle'; 
} 

async function doSomethingInSeries(): Promise<any> { 
    let timeoutId; 

    const delay = new Promise(function(resolve, reject){ 
    timeoutId = setTimeout(function(){ 
     reject(new Error('timeout')); 
    }, 1000); 
    }); 

    // overall timeout 
    return Promise.race([delay, _doSomethingInSeries()]) 
    .then((res) => { 
     clearTimeout(timeoutId); 
     return res; 
    }); 

} 

誰でもミスを?

私に少し匂いがするのは、非同期戦略としてPromisesを使用すると、他の戦略に必要なオブジェクトをあまりにも多く割り当てることになりますが、これは話題にはなりません。

+1

あなたはタイムアウトをクリアしていません'_doSomethingInSeries()'は失敗します。 'try {return await Promise.race(...);}を使うべきです。 } finally {clearTimeout(timeoutId);} } ' – Bergi

関連する問題