对多个 then 方法使用相同的 catch 块
Using same catch block for multiple then methods
鉴于:
- NodeJS v0.10.25
- 已启用所有 Harmony 功能
"use strict"
以及以下代码:
db.connect({
host: DB_HOST,
port: DB_PORT
}).then(function(dbConn) {
console.log('DBASE connected to ' + DB_HOST + ':' + DB_PORT);
db.dbList().run(dbConn).then(function(result) {
if (result.indexOf(SCRIPT_NAME) == -1) throw new Error('unable to locate database ' + SCRIPT_NAME);
dbConn.use(SCRIPT_NAME);
console.log('DBASE bound to ' + SCRIPT_NAME + ' on ' + DB_HOST + ':' + DB_PORT);
db.tableList().run(dbConn)
.then(function(result) {
if (!result) throw new Error(SCRIPT_NAME + ' unable to enumerate tables');
if (!result.length) throw new Error(SCRIPT_NAME + ' has no tables');
console.log('DBASE ' + DB_HOST + ':' + DB_PORT + '/' + SCRIPT_NAME + ' has ' + result.length + ' table' + ((result.length > 1) ? 's' : ''));
}).catch(function(err) {
console.error('DBASE ' + err);
});
}).catch(function(err) {
console.error('DBASE ' + err);
});
}).catch(function(err) {
console.error('DBASE ' + err);
});
注意多个相同的 catch 块:
.catch(function(err) {
console.error('DBASE ' + err);
});
是否有推荐/接受/事实上的方法来跨多个级别的控制结构重用该异常处理程序?
错误会冒泡,直到它们被捕获,因此您不需要多次捕获,并且您可以通过链接您的 promise 而不是嵌套它们来使您的代码更具可读性:
db.connect({
host: DB_HOST,
port: DB_PORT
}).then(function(dbConn) {
console.log('DBASE connected to ' + DB_HOST + ':' + DB_PORT);
// it's important to return if you have a promise so the chain doesn't break
return db.dbList().run(dbConn);
}).then(function(result) {
if (result.indexOf(SCRIPT_NAME) == -1) throw new Error('unable to locate database ' + SCRIPT_NAME);
dbConn.use(SCRIPT_NAME);
console.log('DBASE bound to ' + SCRIPT_NAME + ' on ' + DB_HOST + ':' + DB_PORT);
return db.tableList().run(dbConn);
}).then(function(result) {
if (!result) throw new Error(SCRIPT_NAME + ' unable to enumerate tables');
if (!result.length) throw new Error(SCRIPT_NAME + ' has no tables');
console.log('DBASE ' + DB_HOST + ':' + DB_PORT + '/' + SCRIPT_NAME + ' has ' + result.length + ' table' + ((result.length > 1) ? 's' : ''));
}).catch(function(err) {
console.error('DBASE ' + err);
});
ShanShan 的回答是正确的,但既然你说你在现代 Node 上使用 ES2015,你可以使用更现代的语法:
db.connect({
host: DB_HOST,
port: DB_PORT
}).then(dbConn => {
console.log(`DBASE connected to ${DB_HOST} : ${DB_PORT}`);
return db.dbList().run(dbConn);
}).then(result =>{
if (!result.includes(SCRIPT_NAME))
throw new Error(`unable to locate database ${SCRIPT_NAME}`);
dbConn.use(SCRIPT_NAME);
console.log(`DBASE bound to ${SCRIPT_NAME} on ${DB_HOST} : ${DB_PORT}`);
return db.tableList().run(dbConn);
}).then(result =>
if (!result) throw new Error(`${SCRIPT_NAME} unable to enumerate tables`);
if (!result.length) throw new Error(`${SCRIPT_NAME has no tables`);
console.log(`DBASE ${DB_HOST} : ${DB_PORT}/${SCRIPT_NAME} has ` + `
`${result.length} table ${((result.length > 1) ? 's' : '')}`);
process.on('unhandledRejection', (p) => console.error('DBASE', p)); // global handler
更进一步,如果我们使用发电机泵,代码可以写成:
function co(gen) { // your friendly neighborhood generator pump
var it = gen();
return Promise.resolve().then(function next(v){
let r = it.next(v);
if(r.done) return r.value;
return Promise.resolve(r.value).then(next, e => it.throw(e));
});
}
co(function*() { // console logs ommitted for brevity
const db = yield db.connect({host: DB_HOST, port: DB_PORT });
const list = yield db.dbList().run(dbConn);
if(!result.includes(SCRIPT_NAME))
throw new Error(`unable to locate database ${SCRIPT_NAME}`);
db.use(SCRIPT_NAME);
const tables = db.tableList().run(db);
if(!tables) throw new Error(`${SCRIPT_NAME} unable to enumerate tables`);
if(!tables.length) throw new Error(`${SCRIPT_NAME} has no tables`);
return tables; // this still returns a promise, you can chain off it
});
就是这样,完全平坦,您可以在那里使用同步 try/catch 它会起作用,或者如果您愿意,也可以对结果承诺使用 .catch
。
您可以使用像 bluebird 这样的库来代替上面的 co
函数,这样可以为您提供更好的堆栈跟踪和更快的承诺。
鉴于:
- NodeJS v0.10.25
- 已启用所有 Harmony 功能
"use strict"
以及以下代码:
db.connect({
host: DB_HOST,
port: DB_PORT
}).then(function(dbConn) {
console.log('DBASE connected to ' + DB_HOST + ':' + DB_PORT);
db.dbList().run(dbConn).then(function(result) {
if (result.indexOf(SCRIPT_NAME) == -1) throw new Error('unable to locate database ' + SCRIPT_NAME);
dbConn.use(SCRIPT_NAME);
console.log('DBASE bound to ' + SCRIPT_NAME + ' on ' + DB_HOST + ':' + DB_PORT);
db.tableList().run(dbConn)
.then(function(result) {
if (!result) throw new Error(SCRIPT_NAME + ' unable to enumerate tables');
if (!result.length) throw new Error(SCRIPT_NAME + ' has no tables');
console.log('DBASE ' + DB_HOST + ':' + DB_PORT + '/' + SCRIPT_NAME + ' has ' + result.length + ' table' + ((result.length > 1) ? 's' : ''));
}).catch(function(err) {
console.error('DBASE ' + err);
});
}).catch(function(err) {
console.error('DBASE ' + err);
});
}).catch(function(err) {
console.error('DBASE ' + err);
});
注意多个相同的 catch 块:
.catch(function(err) {
console.error('DBASE ' + err);
});
是否有推荐/接受/事实上的方法来跨多个级别的控制结构重用该异常处理程序?
错误会冒泡,直到它们被捕获,因此您不需要多次捕获,并且您可以通过链接您的 promise 而不是嵌套它们来使您的代码更具可读性:
db.connect({
host: DB_HOST,
port: DB_PORT
}).then(function(dbConn) {
console.log('DBASE connected to ' + DB_HOST + ':' + DB_PORT);
// it's important to return if you have a promise so the chain doesn't break
return db.dbList().run(dbConn);
}).then(function(result) {
if (result.indexOf(SCRIPT_NAME) == -1) throw new Error('unable to locate database ' + SCRIPT_NAME);
dbConn.use(SCRIPT_NAME);
console.log('DBASE bound to ' + SCRIPT_NAME + ' on ' + DB_HOST + ':' + DB_PORT);
return db.tableList().run(dbConn);
}).then(function(result) {
if (!result) throw new Error(SCRIPT_NAME + ' unable to enumerate tables');
if (!result.length) throw new Error(SCRIPT_NAME + ' has no tables');
console.log('DBASE ' + DB_HOST + ':' + DB_PORT + '/' + SCRIPT_NAME + ' has ' + result.length + ' table' + ((result.length > 1) ? 's' : ''));
}).catch(function(err) {
console.error('DBASE ' + err);
});
ShanShan 的回答是正确的,但既然你说你在现代 Node 上使用 ES2015,你可以使用更现代的语法:
db.connect({
host: DB_HOST,
port: DB_PORT
}).then(dbConn => {
console.log(`DBASE connected to ${DB_HOST} : ${DB_PORT}`);
return db.dbList().run(dbConn);
}).then(result =>{
if (!result.includes(SCRIPT_NAME))
throw new Error(`unable to locate database ${SCRIPT_NAME}`);
dbConn.use(SCRIPT_NAME);
console.log(`DBASE bound to ${SCRIPT_NAME} on ${DB_HOST} : ${DB_PORT}`);
return db.tableList().run(dbConn);
}).then(result =>
if (!result) throw new Error(`${SCRIPT_NAME} unable to enumerate tables`);
if (!result.length) throw new Error(`${SCRIPT_NAME has no tables`);
console.log(`DBASE ${DB_HOST} : ${DB_PORT}/${SCRIPT_NAME} has ` + `
`${result.length} table ${((result.length > 1) ? 's' : '')}`);
process.on('unhandledRejection', (p) => console.error('DBASE', p)); // global handler
更进一步,如果我们使用发电机泵,代码可以写成:
function co(gen) { // your friendly neighborhood generator pump
var it = gen();
return Promise.resolve().then(function next(v){
let r = it.next(v);
if(r.done) return r.value;
return Promise.resolve(r.value).then(next, e => it.throw(e));
});
}
co(function*() { // console logs ommitted for brevity
const db = yield db.connect({host: DB_HOST, port: DB_PORT });
const list = yield db.dbList().run(dbConn);
if(!result.includes(SCRIPT_NAME))
throw new Error(`unable to locate database ${SCRIPT_NAME}`);
db.use(SCRIPT_NAME);
const tables = db.tableList().run(db);
if(!tables) throw new Error(`${SCRIPT_NAME} unable to enumerate tables`);
if(!tables.length) throw new Error(`${SCRIPT_NAME} has no tables`);
return tables; // this still returns a promise, you can chain off it
});
就是这样,完全平坦,您可以在那里使用同步 try/catch 它会起作用,或者如果您愿意,也可以对结果承诺使用 .catch
。
您可以使用像 bluebird 这样的库来代替上面的 co
函数,这样可以为您提供更好的堆栈跟踪和更快的承诺。