异步给回调已经调用错误?

async giving callback already called error?

我正在尝试实现以下场景。但是在执行时出现错误 Uncaught Error: Callback was already called.

谁能发现我做错了什么?

async.forEachOf(code,function(item, index, done){
    var currentItemId = item.id;    
    var subitemCount = item.subitem;
    for(var k=0; k< subitemCount ; k++){
         $.ajax({
            url: 'api/item' + k,
            success: function(result) {              
             code["allSub"].push(result);
             done();
            },
            error: function(err) {                
                done(err);             
            }
        })
    }
},function(){
    console.log(code);
});

问题在于 for(var k=0; k< subitemCount ; k++){ 声明。

请注意,对于每个 item.subitem,您都会拨打一个 ajax 电话。在每个调用 return 之后,您都在调用 done() 回调。因此,代码实际上多次调用回调(即 done())。每个 ajax 调用一次,因此每个 item.subitem.

调用一次

这就是您遇到 未捕获错误:已调用回调的原因。

为了避免这种情况,您需要制作另一个 async.forEachOf 而不是

试试这个:

async.forEachOf(code,function(item, index, doneItem){
    var currentItemId = item.id;    
    var subitemCount = item.subitem;
    async.forEachOf(subitemCount, function (subItem, subItemIndex, subItemDone){
        $.ajax({
            url: 'api/item' + subItemIndex,
            success: function(result) {              
                code["allSub"].push(result);
                subItemDone();
            },
            error: function(err) {                
                subItemDone(err);             
            }
        })
    }, function(err) {
        //Called once all the current item's subItems ajax calls were finished 
        doneItem(err);
    }


},function(){
    //Called once all items in "code" finished their own subItem ajax calls
    console.log(code);
});

如果item.subitem是一个数值而不是数组,你可以尝试使用async.times

async.forEachOf(code,function(item, index, doneItem){
    var currentItemId = item.id;    
    var subitemCount = item.subitem;
    async.times(subitemCount, function (subItemIndex, subItemDone){
        $.ajax({
            url: 'api/item' + subItemIndex,
            success: function(result) {     
                code["allSub"].push(results);         
                subItemDone();
            },
            error: function(err) {                
                subItemDone(err);             
            }
        })
    }, function(err, results) {
        //Called once all subItem ajax calls were finished
        doneItem(err);
    }


},function(){
    //Called once all items in "code" finished their own subItem ajax calls
    console.log(code);
});