Node.js asyncAuto场景下Callback was already called报错如何解决
Node.js async库回调重复调用问题解决方案
问题根因
你使用的async.js库的asyncAuto方法存在隐式规则:如果任务函数返回了thenable对象(Promise、类Promise实例),async会自动将该对象的执行结果作为任务完成的结果,隐式调用一次任务回调。
你在代码中使用return cbk(null, result)的写法,会将cbk函数的返回值直接作为任务函数的返回值。当进入!args.is_table分支时,cbk调用后的返回值刚好是thenable对象,就会触发async的自动回调逻辑,等于你手动调用一次cbk、async自动调用一次,就触发了Callback was already called报错。
而走else分支时cbk返回值不是thenable,所以不会触发隐式调用,运行正常。
修复方案
方案1:调整回调调用写法(成本最低)
不要在调用回调时直接return其返回值,改为调用回调后单独return,切断隐式触发的条件:
allForwards: ['forwards', ({forwards}, cbk) => { if (!args.is_table) { cbk(null, {peers: forwards.peers}); return; } const isWideSize = !size || size.get().width > wideSizeCols; cbk(null, { peers: forwards.peers, rows: [] .concat([notNull([ 'Alias', 'Earned In', 'Earned Out', 'Inbound', 'Outbound', !!isWideSize ? 'Public Key' : null, ]).map(n => !args.is_monochrome ? bold(n) : n)]) .concat(forwards.peers.map(peer => { return notNull([ chartAliasForPeer({ alias: peer.alias, icons: peer.icons, is_disconnected: peer.is_disconnected, is_forwarding: peer.is_forwarding, is_inactive: peer.is_inactive, is_pending: peer.is_pending, is_private: peer.is_private, public_key: peer.public_key, }).display, formatTokens({ is_monochrome: args.is_monochrome, tokens: peer.liquidity_outbound, }).display, !!isWideSize ? peer.public_key : null, ]); })), }); return; }],
方案2:改用async/await写法(更易维护)
async.js的新版本已经原生支持async函数作为任务执行体,不需要手动调用回调,从根源上避免重复调用问题:
allForwards: ['forwards', async ({forwards}) => { if (!args.is_table) { return {peers: forwards.peers}; } const isWideSize = !size || size.get().width > wideSizeCols; return { peers: forwards.peers, rows: [] .concat([notNull([ 'Alias', 'Earned In', 'Earned Out', 'Inbound', 'Outbound', !!isWideSize ? 'Public Key' : null, ]).map(n => !args.is_monochrome ? bold(n) : n)]) .concat(forwards.peers.map(peer => { return notNull([ chartAliasForPeer({ alias: peer.alias, icons: peer.icons, is_disconnected: peer.is_disconnected, is_forwarding: peer.is_forwarding, is_inactive: peer.is_inactive, is_pending: peer.is_pending, is_private: peer.is_private, public_key: peer.public_key, }).display, formatTokens({ is_monochrome: args.is_monochrome, tokens: peer.liquidity_outbound, }).display, !!isWideSize ? peer.public_key : null, ]); })), }; }],
内容的提问来源于stack exchange,提问作者Nitesh
相关产品推荐
相关产品推荐

