【问题标题】:async - callback already used errorasync - 回调已使用错误
【发布时间】:2023-03-21 12:27:01
【问题描述】:

我收到“回调已使用”错误,我不知道为什么。我正在使用异步并且想要链接两个函数,因为第二个函数取决于第一个函数来完成。

我是 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()
      });
    }
  });
}

【问题讨论】:

    标签: node.js asynchronous


    【解决方案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);
    

    【讨论】:

    • 我还添加了 getCname 函数作为参考。据我了解,getCname 会对 async.each 进行回调。只有在 async.each 遍历整个数组之后,它才会执行最终的回调,从而使 async.series 继续执行下一个函数。 getCname 和 getCdn 之间有什么不同,使 getCname 可以正常工作,而 getCdn 抛出回调? getCdn 是否应该为每次迭代对 async.each 进行回调?我的断线在哪里?
    • 在任何使用函数的异步方法中,回调基本上都是用来表示“这个函数完成处理”。如果您来自阻塞语言,请将回调视为返回语句。由于节点的非阻塞性质,这是必要的。 getCdn 函数为每个循环调用回调,这是错误的,因为该函数实际上并没有完全完成处理。相反,getCname 函数只会调用一次回调,当它完成工作时是正确的。
    • 要习惯回调,您可以将刚才写为callback() 的行更改为return callback()。这会让你知道它应该做什么。如果您的代码仍然有效,则说明您正确使用了回调!
    猜你喜欢
    • 2014-08-19
    • 2017-09-15
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2017-06-23
    • 2020-11-19
    相关资源
    最近更新 更多