Node.js使用async库遇Callback was already called错误求解决
解决async库「Callback was already called」错误 + 实现多内部回调完成后触发外部回调
嘿,我刚看完你的代码,立马就发现问题所在了——你现在的写法会多次调用innercallback,这就是触发「Callback was already called」错误的核心原因!咱们一步步拆解解决:
错误根源分析
你在client.execute的回调里直接调用了innercallback,而且每个odId下有两个client.execute,再加上外层的myJson.matches和oMatches.ids循环,相当于一个data项会触发N次innercallback调用。但async的forEachLimit要求每个迭代(也就是每个data)只能调用一次innercallback,多调用就会报错。
实现需求的正确姿势
你的需求是「两个内部回调全部完成后再执行外部回调」,更准确地说,是每个data对应的所有异步操作(所有匹配到的odId下的两个client.execute)全部完成后,才调用一次innercallback。咱们可以用async的each和parallel来嵌套管理这些异步任务:
修改后的代码
async.forEachLimit(inData, 25, function (data, innercallback) { // 用async.each遍历myJson.matches,替代普通forEach(因为内部有异步操作) async.each(myJson.matches, function (oMatches, matchCallback) { if (data.$.id == oMatches.SourceId) { // 遍历当前oMatches下的所有ids async.each(oMatches.ids, function (odId, idCallback) { // 用async.parallel并行执行两个client.execute操作 async.parallel([ function (taskCallback) { client.execute( `g.addV('test').property('id', "${data.$.id}")`, {}, function (err) { setTimeout(function () { taskCallback(err); }, 2000); } ); }, function (taskCallback) { client.execute( `g.V('${data.$.id}').addE('matches').to(g.V('xyz'))`, {}, function (err) { setTimeout(function () { taskCallback(err); }, 2000); } ); } ], function (err) { // 两个并行任务完成后,触发idCallback,继续下一个odId idCallback(err); }); }, function (err) { // 当前oMatches下的所有ids处理完成,触发matchCallback matchCallback(err); }); } else { // 没有匹配的话,直接触发matchCallback,继续下一个oMatches matchCallback(null); } }, function (err) { // 所有myJson.matches处理完成,才调用innercallback(每个data只调用一次!) innercallback(err); }); }, outercallback);
关键说明
- 避免重复调用回调:每个层级的异步任务都用对应的async方法管理,确保只有当该层级所有操作完成后,才调用下一层级的回调,最终每个
data只会调用一次innercallback。 - 并发控制:外层的
forEachLimit(inData, 25)已经控制了同时处理25个data,内部的parallel让每个odId下的两个请求并行执行,既满足Azure的配额限制,又保证效率。 - setTimeout的使用:你加的2000ms延迟可以有效降低请求频率,不过如果担心延迟累积,也可以考虑把
setTimeout放在client.execute调用之前,或者用async.retry处理可能的配额超限问题。
额外小优化
可以用模板字符串(反引号`)来拼接Gremlin语句,比字符串拼接更清晰,也减少转义错误的概率,我在代码里已经帮你改了~
内容的提问来源于stack exchange,提问作者userMod2
相关产品推荐
相关产品推荐

