一句話,redis實例方法都會返回boolean值,表示當前服務是否可用。這個值更新不及時時,就會在回調中返回err。
背景
今天老司機提了這個問題。像下面的代碼
// redis v2.8.0
const redis = require('redis');
const rdb = redis.createClient();
rdb.on('error', err => console.error('全局捕獲', err));
......
rdb.get(key, (err, ret) => {
if (err) console.log('局部捕獲', err)
});
如果程序執行中,Redis server斷開了,全局會捕獲到錯誤,rdb.get()中的回調根本執行不到。
那么如果希望,server斷開時,rdb.get()取不到的情況下,可以取一個默認值,而不是一直卡著,怎么做呢?
npm上似乎沒有找到判斷的方法。
閱讀redis源碼,有這么一段:
RedisClient.prototype.internal_send_command = function (command_obj) {
......
if (this.ready === false || this.stream.writable === false) {
......
return false;
}
}
這個原型函數,就是執行redis實例方法時,最后的返回。可以看到,redis內部維持了一些狀態量,表示服務是否可用;不可用時,方法直接返回false。
原來redis庫內部默認設置自動重連時,會不斷檢查和重置this.ready狀態。
但是,經過高頻啟動和關閉server測試,這個狀態當然不是即時改變的。當查詢時,如果this.ready=true但服務已經關了,就會拋出錯誤,好在這是可以在回調函數中捕獲的。
最佳實踐
function get(key) {
return new Promise((resolve, reject) => {
const isAvailable = rdb.get(key, (err, ret) => {
if (err) {
if (err.code === 'UNCERTAIN_STATE') return resolve(false);
return reject(err);
}
resolve(ret);
});
if (!isAvailable) return resolve(false);
});
}
~async function () {
let val = await get(key);
if (val === false) {
// 說明數據庫斷開,查詢失敗
}
}();