#javascript #node.js #async.js
#javascript #node.js #async.js
Вопрос:
Я понимаю, почему я получаю эту ошибку, однако я понятия не имею, как это исправить. Вот как выглядит моя первая функция:
Все, что я делаю, это выполняю запрос get для всех моих URL, которые хранятся в базе данных, а затем для каждого ответа URL я просматриваю тело и сохраняю информацию о значениях, вызывая saveInformation(value)
или saveInfoTwo(value)
function getUrlInfo(urls, callback) {
urls.map(function(url) {
request.get(urls, {
timeout: 1500
}, function(error, response, body) {
if (error) {console.log(error);
} else {
parseString(body, function(error, result) {
if (error) {console.log(error);
} else {
result.Values.forEach(function(listValues) {
listValues.forEach(function(value) {
saveInformation(value);
});
saveInfoTwo(value);
});
}
});
}
callback(null);
});
});
}
Мой асинхронный водопад выглядит следующим образом:
async.waterfall([
getUrls,
getUrlInfo
], function(err, result) {
mongoose.connection.close();
});
Where getUrls
— это просто метод, который ищет все URL-адреса и добавляет их в urls
массив, чтобы getUrlInfo
можно было его использовать.
function getUrls(callback) {
var urls = [];
urlSchema.find(function(error, data) {
data.forEach(function(result) {
clusters.push(result.url);
});
callback(null, urls);
});
}
Я использую mongodb в качестве своей базы данных.
Это отлично работает, когда есть только один URL. Как только я добавляю другой URL, я получаю эту ошибку:
Error: Callback was already called.
Теперь, после попытки отладки, кажется, что все работает нормально для первого URL, а затем, когда второй URL завершает цикл foreach, выдается ошибка.
Как я могу это исправить?
Я почти уверен, что обратный вызов в моем getUrlInfo()
ожидает завершения всех URL-адресов и циклов foreach, а затем продолжается? — я думаю, это не тот случай.
Любая помощь была бы оценена!
Подводя итог: как я могу предотвратить появление ошибки при добавлении другого URL?
Комментарии:
1. Ну, не использовать
urls.map
какой цикл, который будет вызыватьсяcallback
несколько раз?2. Вместо этого используйте
async.map(urls, …, callback)
3. Не могли бы вы, пожалуйста, показать нам
getUrls
? Вероятно, он вызывает свой обратный вызов более одного раза.4. Не могли бы вы показать мне async.map с примером моего кода, пожалуйста? Я новичок в обратных вызовах. @Gil Z, сейчас обновляю ответ
Ответ №1:
Ваша карта вызывает функцию для первого URL, когда она завершается, callback
вызывается. Когда выполняется второй, по завершении он будет вызываться callback
снова, таким образом, у вас возникает эта ошибка.
Решение: дождитесь завершения всех URL-адресов, а затем вызовите обратный вызов.
Как сказал @Bergi в комментариях, вы можете использовать асинхронную карту
function getUrlInfo(urls, callback) {
async.map(urls, function(url, cb) {
//do what you must
cb();
}, callback);
}