2016-05-09 14 views
12

Tôi đang sử dụng Node.js và TypeScript và tôi đang sử dụng async/await. Đây là trường hợp thử nghiệm của tôi:Hết giờ trong async/await

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

Tôi muốn đặt thời gian chờ cho chức năng tổng thể. I E. nếu res1 mất 2 giây, res2 mất 0,5 giây, res3 mất 5 giây Tôi muốn có thời gian chờ sau 3 giây để tôi phát hiện lỗi.

Với setTimeout cuộc gọi bình thường là một vấn đề bởi vì phạm vi bị mất:

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

Và tôi không thể bắt nó với bình thường Promise.catch:

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

Bất kỳ ý tưởng về làm thế nào để giải quyết?

+0

Bạn có đang sử dụng thư viện lời hứa cụ thể không? – Bergi

+0

Không, chỉ là lời hứa tiêu chuẩn. – nkint

+0

Vì vậy, 2 + 0,5 + 5 + 3 làm cho một thời gian chờ là 11,5 giây? – Bergi

Trả lời

19

Bạn có thể sử dụng Promise.race để thực hiện một thời gian chờ:

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

Bạn không thể sử dụng mà không cần setTimeout gói nó trong một lời hứa.

+0

Tôi nhận được giải pháp tương tự, cảm ơn anyway! – nkint

+0

Tại sao không cần 'clearTiimeout'? – nkint

+0

@nkint: Chúng tôi không cần xóa nó vì từ chối không được xem xét khi 'doSomethingInSeries()' giải quyết trước tiên. Chúng ta có thể xóa nó, nhưng điều đó sẽ khá phức tạp (tối ưu 'chủng tộc' sẽ có cách để hủy bỏ những lời hứa chậm hơn, nhưng điều đó là không thể với những lời hứa gốc). – Bergi

2

Ok tôi thấy cách này:

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

} 

lỗi ai?

Những điều có mùi đối với tôi là sử dụng Promises như chiến lược đồng bộ sẽ gửi cho chúng tôi phân bổ quá nhiều đối tượng mà một số chiến lược khác cần nhưng đây là chủ đề không chính xác.

+1

Bạn không xóa hết thời gian chờ nếu '_doSomethingInSeries()' không thành công. Bạn nên sử dụng 'try {return await Promise.race (…); } cuối cùng {clearTimeout (timeoutId); } ' – Bergi

Các vấn đề liên quan