0
我收到'回調已用'錯誤,我不知道爲什麼。我正在使用異步並希望鏈接兩個函數,因爲第二個函數依賴於要完成的第一個函數。異步 - 已使用回調錯誤
我是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()
});
}
});
}
我還添加了getCname功能作爲參考。根據我的理解,getCname會對async.each進行回調。只有在遍歷整個數組的async.each之後,它纔會執行最後的回調,這會使async.series移動到下一個函數。 getCname和getCdn有什麼不同,getCname可以正常工作,並且getCdn會引發回調?應該getCdn爲每次迭代回調async.each?我的斷開連接在哪裏? –
在任何使用函數的異步方法中,回調基本上用於說「此函數已完成處理」。如果您來自阻塞語言,請將回調視爲返回聲明。由於節點的非阻塞性質,這是必需的。 'getCdn'函數爲每個循環調用回調函數,這是錯誤的,因爲函數實際上並未完成處理。相反,'getCname'函數只會在回調完成後調用回調函數。 –
爲了適應回調,您可以更改剛剛讀取'callback()'以讀取'return callback()'的行。這會讓你知道它應該做什麼。如果你的代碼仍然有效,那麼你正確地使用回調了! –