2016-05-09 27 views
12

में टाइमआउट मैं नोड.जेएस और टाइपस्क्रिप्ट के साथ हूं और मैं async/await का उपयोग कर रहा हूं। यह मेरा परीक्षण का मामला है: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

@ एनकिंट: हमें इसे साफ़ करने की आवश्यकता नहीं है क्योंकि अस्वीकृति को तब नहीं माना जाता है जब 'कुछ कुछ इनसाइरीज()' पहले सुलझाता है। हम इसे साफ़ कर सकते हैं, लेकिन यह जटिल होगा (बेहतर रूप से 'रेस' के पास धीमे वादे को रद्द करने का कोई तरीका होगा, लेकिन मूल वादे के साथ यह संभव नहीं है)। – Bergi

2

ठीक है, मैं इस तरह से मिला:

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; 
    }); 

} 

कोई भी त्रुटि नहीं है?

चीजें जो मुझे थोड़ा गंध करती हैं वह यह है कि वादा का उपयोग एसिंच्रोनिटी रणनीति के रूप में हमें कई अन्य ऑब्जेक्ट आवंटित करने के लिए भेज देगा जो कुछ अन्य रणनीति की ज़रूरत है लेकिन यह विषय-वस्तु है।

+1

पर एक नज़र डालें, यदि आप टाइमआउट को साफ़ नहीं कर रहे हैं '_do SomethingInSeries() 'विफल रहता है। आपको 'try {return का इंतजार करना चाहिए Promise.race (...); } अंत में {clearTimeout (timeoutId); } ' – Bergi