簡體   English   中英

如何使用JS promises捕獲異步錯誤?

[英]How can I catch an asynchronous error using JS promises?

是否可以使用promises的ES6 .catch語法捕獲異步錯誤? 例如,以下不起作用(.catch不捕獲錯誤):

new Promise((resolve, reject)=>{
    setTimeout(()=>{throw new Error("uh oh")}, 1);
}).then(number=>{
    console.log("Number: " + number);
}).catch(e=>{
    console.log("Error: " + e);
});

但是這個同步版本可以:

new Promise((resolve, reject)=>{
    throw new Error("uh oh");
}).then(number=>{
    console.log("Number: " + number);
}).catch(e=>{
    console.log("Error: " + e);
});

是唯一能夠執行以下操作的解決方案,使用try / catch塊並reject catch中的錯誤?

new Promise((resolve, reject)=>{
    try {
        setTimeout(()=>{throw new Error("uh oh")}, 1);
    }
    catch(e) {
        reject(e);
    }
}).then(number=>{
    console.log("Number: " + number);
}).catch(e=>{
    console.log("Error: " + e);
});

為了這個問題,假設拋出錯誤的代碼部分在另一個命名函數中,因此它無法訪問reject函數。

謝謝!!

編輯: 這是我在JSFiddle中想要做的更完整的例子。

Promise構造函數中使用resolve()reject() 處理onRejected.catch()處理錯誤。

注意,一旦處理了錯誤,就onFulfilled在鏈接onFulfilled .then() onFulfilled ,如果有的話,除非在onRejected.catch()使用throw ,以顯式地將錯誤傳遞給鏈接.then(_, onRejected).catch()

 function fn() { throw new Error("uh oh") } new Promise((resolve, reject) => { setTimeout(() => { try { resolve(fn()) } catch (e) { reject(e) } }, 1); }).then(number => { console.log("Number: " + number); }, e => { console.log("Error: " + e); }); 

沒有辦法像第一個例子那樣捕獲錯誤。 這里的問題是您使用的是Explicit Promise Construction Antipattern。 您正在嘗試讓Promise構造函數執行更多操作。

相反,您應該宣傳少量的異步功能,並在此基礎上構建。 在這種情況下,這將涉及產生在解決之前等待一定時間的承諾。 大多數第三方承諾庫已經有了.delay()方法,但創建自己的方法非常簡單:

let delay = duration => new Promise(resolve => setTimeout(resolve, duration));

然后你可以在此基礎上構建,並輕松捕獲錯誤:

 let delay = duration => new Promise(resolve => setTimeout(resolve, duration)); delay(1) .then(() => { throw new Error("uh oh"); }) .then(number => { console.log("Number: " + number); }).catch(e => { console.log("Error: " + e); }); 

“為了這個問題,假設拋出錯誤的代碼部分在另一個命名函數中,因此它無法訪問拒絕函數。” - 克里斯托弗Shroba

“這個(你的代碼中不存在)函數會返回一個Promise嗎?” - Jaromanda X.

“是的,另一個函數通常會返回一個promise, 但由於該函數內部的異步函數拋出了一個Error ,整個函數都會拋出一個Error。” - 克里斯托弗Shroba

那么下次發布您的代碼時,因為您用英語描述問題的能力永遠不會像實際代碼那樣好。 “異步函數”是指一個返回promise的函數嗎? 如果是這樣的話 ...


錯誤在你的Promises中的深度並不重要。 下面是一個例子功能three它調用的函數two它調用一個函數one具有潛力拋出一個錯誤的JSON形式不佳的情況下。 每一步都使最終計算的寶貴貢獻,但在事件one拋出一個錯誤,它會冒泡通過承諾的整個鏈條。

 const one = (json) => new Promise((resolve, reject) => { resolve(JSON.parse(json)) }) const two = (json) => one(json).then(data => data.hello) const three = (json) => two(json).then(hello => hello.toUpperCase()) three('{"hello":"world"}').then(console.log, console.error) // "WORLD" three('bad json').then(console.log, console.error) // Error: unexpected token b in JSON at position 0 


否則通過“異步函數”你的意思是它是一個不返回Promise並且可能使用延續的函數? 在這種情況下,我們將修改one以在承諾中包裝異步函數,然后twothree將工作相同。 重要的是,我沒有使用try / catch在我的任何承諾的功能

 // continuation passing style async function const asyncParse = (json, k) => { try { k(null, JSON.parse(json)) } catch (err) { k(err) } } // one now wraps asyncParse in a promise const one = (json) => new Promise((resolve, reject) => { asyncParse(json, (err, data) => { if (err) reject(err) else resolve(data) }) }) // everything below stays the same const two = (json) => one(json).then(data => data.hello) const three = (json) => two(json).then(hello => hello.toUpperCase()) three('{"hello":"world"}').then(console.log, console.error) // "WORLD" three('bad json').then(console.log, console.error) // Error: unexpected token b in JSON at position 0 


哦,如果你有一個函數f ,它不能以這兩種方式中的任何一種運行 - 即拋出錯誤但不返回承諾或將錯誤發送到延續的函數 - 你正在處理一塊垃圾和你寫的代碼取決於f也將是垃圾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM