從documentation of the redis npm package,很明顯,它採用標準的節點樣式的回調。在標準的Node-style回調中,傳遞給您提供的回調的第一個參數是錯誤或null
;這就是報告錯誤的地方和方式。 (你甚至在你的代碼中定義了一個叫err
的參數。)它們不能被try/catch
捕獲,因爲在錯誤發生很久以前,控制已經超出了try/catch
(事實上它已經不在函數中)。
所以,你會處理這樣的:
module.exports = (req, res, next) => {
const redis = require('redis')
const client = redis.createClient()
client.select('2d', (err) => { // instead of 2 number, i use '2d' string, to generate an error on purpose
if (err) {
// Handle error here
err.type = 'SilentSystem'
next(err)
} else {
// Handle success here
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
client.set(ip, true, 'EX', 120, (err, rep) => {
if (err) {
err.type = 'SilentSystem'
next(err)
} else {
next()
}
})
}
})
}
在評論你說:
我實際的代碼是一個比較複雜的,所以我想避免打電話,以免使用try
重複呼叫if(err)
和next(err)
。在這裏處理錯誤有什麼更好的方法(不太詳細)?
不幸的是,這就是節點式回調的本質。一種選擇是給自己一個過濾功能,讓所有這些結果都通過,所以你的常見錯誤處理代碼就在那裏。
但是:您可能會考慮使用一個「promisifies」節點式回調函數庫,以便您可以使用promise,並使用它們的鏈接機制來完成集中式錯誤處理。 (一個這樣的包是promisify
,但還有其他的。)隨着client.select
,client.set
「promisified」版本等,這些代碼可能看起來像這樣:
module.exports = (req, res, next) => {
const redis = require('redis')
const client = makeNiftyPromiseVersionOf(redis.createClient())
client.select('2d')
.then(data => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
return client.set(ip, true, 'EX', 120)
})
.then(() => {
next()
})
.catch(err => {
err.type = 'SilentSystem'
next(err)
})
}
注意的錯誤處理是如何在鞏固結束;如果client.select
中有錯誤,則跳過then
回調,並將控制傳遞給catch
。如果不是,則執行then
回調並執行client.set
,並且其中的任何錯誤也將轉到該catch
。
這也將打開大門,使用ES2017的async
/await
在同步風格編寫異步代碼:
module.exports = (req, res, next) => {
(async() => {
const redis = require('redis')
const client = makeNiftyPromiseVersionOf(redis.createClient())
try {
const data = await client.select('2d');
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
await client.set(ip, true, 'EX', 120)
next()
} catch (err) {
err.type = 'SilentSystem'
next(err)
}
})();
}
附註:我會刪除require
呼叫出來的導出函數的 ,而是在模塊級別上執行:
const redis = require('redis')
module.exports = {
// ...
}
我的實際代碼有點複雜所以我試圖避免調用if(err),然後使用try返回next(err)。在這裏處理錯誤有什麼更好的方法(不太詳細)? –
*嘗試避免重複調用,如果(err)和next(err)應該讀取 –
@ S.Schenk:不幸的是,這就是節點式回調的本質。我用一個建議添加了答案的結尾。 –