async - 回调已经使用错误

时间:2014-04-13 19:25:21

标签: node.js asynchronous

我收到了'已经使用过的回调'错误,我不知道为什么。我正在使用异步并希望链接两个函数,因为第二个函数依赖于要完成的第一个函数。

我是Node.js的新手,仍然围绕着异步/回调。非常感谢你帮忙。

getCdn接受cnames,如果cname是CDN的一部分,它会将结果推送到名为cdnAttrs的全局变量中。

function getCdn(cnameDict, callback) {
  // cdnAttributes contains associative array with each web attribute: {name_in_db : code_snippet_to_find_in_cname}
  for (var key in cdnAttributes) {
    if (cdnAttributes.hasOwnProperty(key)) {
      var snippet = -1;
      // some technologies contain multiple code snippets, in that case they are stored as array. Single code snippets are stored as string
      if (!Array.isArray(cdnAttributes[key])) {
        snippet = cnameDict['cname'].indexOf(cdnAttributes[key])
      }
      else {
        // check each code snippet within the array, if any match the source code, update 'snippet'
        for (var n = 0; n < cdnAttributes[key].length; n++) {
          var val = cnameDict['cname'].indexOf(cdnAttributes[key][n])
          if (val > -1) {
            snippet = val
          }
        }
      }
      // if attribute found in tag, create cdnAttrs[cdn] = [{from: hostname, proof: cname}, {from: hostname2, proof: cname2}, ...]
      if (snippet > -1) {
        try {
          cdnAttrs[key].push(cnameDict);
        }
        catch (e) {
          cdnAttrs[key] = [];
          cdnAttrs[key].push(cnameDict);
        }
        callback();
      } else {
        callback();
      }
    } else {
      callback();
    }
  }
}

我的异步功能如下所示:

async.series([
  // THIS FUNCTION WORKS FINE... 
  function(callback) {
    async.each(toCheck, function(hostname, callback) {
      getCname(hostname, callback);
    },callback);
  },
  // THIS FUNCTION RETURNS RETURNS Error("Callback was already called.")
  function(callback) {
    async.each(toCheckCnames, function(cnameDict, callback) {
      getCdn(cnameDict, callback);
    },callback);
  }
], function(err){
  if(err) {
    console.log('ERROR');
  }else{
    console.log('toCheckCnames is done: '+JSON.stringify(toCheckCnames));
    console.log('cdnAttrs is done: '+JSON.stringify(cdnAttrs));
  }
})

getCnames函数有效:

function getCname(hostname, callback){
  dns.resolve(hostname, 'CNAME', function(error, cname) {
    if (cname) {
      toCheckCnames.push({from: hostname, cname: cname[0]});
        callback();
      }
    // if not CNAMEd, check SOA on www.domain.com and domain.com
    else {
      if (hostname.slice(0,4) == 'www.') {
        hostname = hostname.slice(4);
      }
      nativedns.resolve(hostname, 'SOA', function(error, records) {
        if(!error && records) {
          toCheckCnames.push({from: hostname, cname: records[0]['primary']});
          callback();
        }
        else if (!error) {
          hostname = 'www.'+ hostname
          nativedns.resolve(hostname, 'SOA', function(error, records) {
            if (!error) {
              toCheckCnames.push({from: hostname, cname: records[0]['primary']});
              callback();
            }
            else callback()
          });
        }
        else callback()
      });
    }
  });
}

1 个答案:

答案 0 :(得分:1)

您的getCdn函数是一个循环,它将在每次迭代后调用回调。如果调用回调旨在停止循环执行,则可以执行return callback()。否则,您需要重新组织代码,以便仅在函数完成时调用一次回调。

更新:

您还可以简化async.each调用:

// Was this
async.each(toCheck, function(hostname, callback) {
  getCname(hostname, callback);
},callback);

// Could be this
async.each(toCheck, getCname, callback);