Javascript - 為什麼 Error 是空物件?

Javascript - 為什麼 Error 是空物件?

在研究 Async.js waterfall 的時候,感覺像被 javascript 給陰到了一樣

考慮下列的程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const Async = require('async');
const axios = require('axios');

async function func1() {
return axios({
url: 'http://www.google.com',
method: 'GET',
})
.then(res => {
console.log('function 1:', res.status, res.statusText);
return res.status;
})
.catch(error => {
console.log('阿伯~出事了!阿伯!', error);
throw error;
});
}

function func2(status, callback) {
console.log('function 2:', status);
callback(null, status);
}

Async.waterfall([
func1,
func2,
], (error, result) => {
if (error) console.log(error)
else {
console.log('result: ', result);
}
});

沒發生錯誤時會輸出

1
2
3
function 1: 200 OK
function 2: 200
result: 200

但只要丟出一個錯誤

1
2
3
4
5
6
7
8
9
async function func1() {
// ...
.then(res => {
console.log('function 1:', res.status, res.statusText);
throw "Test error";
return res.status;
})
// ...
}

碰!

1
2
3
4
5
function 1: 200 OK
阿伯~出事了!阿伯! Test error
Error: Test error
at /Users/hao/Projects/nchc/xportal/backend/node_modules/async/dist/async.js:173:65
at processTicksAndRejections (internal/process/task_queues.js:93:5)

asyncjs 會先拋出一個奇怪的錯誤,如果先去 google 的話,會覺得這個錯誤好像是 unhandledRejection 的問題

所以我開始找程式碼裡到底有哪裡沒加到,然後全部加過一輪後,一樣爆炸

證明這個思路不對,我開始嚐試走別條路

因為錯誤是 waterfall print error 的時候出現

我一度以為是 aysnc function 跟 非async function 不能這樣混用,又測試了多種寫法

結果也通通爆炸,呀哈哈哈~ ( σ ゚∀ ゚) ゚∀゚)σ

最後試著用別的方式印出 error

1
2
3
4
5
6
7
8
9
Async.waterfall([
func1,
func2,
], (error, result) => {
if (error) console.log(JSON.stringify(error))
else {
console.log('result: ', result);
}
});

喔喔!事情終於有了進展,錯誤沒有跑出來了!

1
2
3
function 1: 200 OK
阿伯~出事了!阿伯! Test error
{}

可是為什麼是空物件呢…?
又經歷了各種嚐試,之後突然想到一件事情
我一直以為是 asyncjs 的寫法錯誤,才會造成 throw 出來的 error 接不到
可是如果是 javascript 的 error 本來就印不出來呢?

從這個思路終於找到問題,不是 asyncjs 不能 async 跟 非async 混用,而是 你沒辦法用 JSON.stringify() 去顯示 Javascript 的 Error 型態

Why are my JS promise catch error objects empty?
Is it not possible to stringify an Error using JSON.stringify?

主要的原因在於 asyncjs 的 waterfall 在接到 throw error 的時候,會把它包裝成 error 的型態,在 callback 的時候當然沒辦法直接印出來

比較簡單解決的方法是去存取 error 的 message

1
2
3
4
5
6
7
8
9
10

Async.waterfall([
func1,
func2,
], (error, result) => {
if (error) console.log(error.message)
else {
console.log('result: ', result);
}
});
1
2
3
function 1: 200 OK
阿伯~出事了!阿伯! Test error
Test error

為了這種初學者的問題卡了半天,學藝不精,真是慚愧 ( ´•̥̥̥ω•̥̥̥` )


Javascript - 為什麼 Error 是空物件?
http://www.haohardtolive.com/2021/07/17/Javascript-Print-Error/
Author
Hao
Posted on
July 17, 2021
Licensed under