我遇到了一个问题,当我从瀑布函数中调用一个正在执行异步作业的函数时,瀑布不会等待它结束,它会向右移动到最后的“错误处理”瀑布的功能。
我希望瀑布的目的是使事物同步并等待,所以要么我不理解这个概念,要么我做错了。
我的瀑布:
async.waterfall([
function(callback){
// If there is no such file error is thrown and next iteration of the loop starts
var prepend="processed__"
var fileName = prepend + configFile.importFileName;
util.log("Checking if there is any processed file on the SFTP matching one in schedule config: "+fileName);
sftpHandler.checkIfExists(generalConfig.sftpPathToImportFiles, fileName, callback);
},
function(callback) {
var oldPrepend="processed__"
var oldName = oldPrepend+configFile.importFileName;
var newPrepend = "being_imported__";
var newName = newPrepend+configFile.importFileName;
var path = generalConfig.sftpPathToImportFiles;
var oldPath = path + oldName;
var newPath = path + newName;
util.log("Going to rename the file from: "+oldName+" to: "+newName);
sftpHandler.renameFileOnSftp(oldPath, newPath, callback);
},
function(callback) {
var criterion = {'SCHID':configFile.SCHID, 'Status': 'queued'};
util.log("Reading data from DB. Criterion: "+JSON.stringify(criterion));
MongoClient.readData(criterion, generalConfig.RecordModel, callback);
},
function(docs, callback) {
// Check if there are any data in the DB for the processed csv file, if not, archive the file, else do bulk import
if (docs){
util.log("Data retrieved: "+JSON.stringify(docs));
callback(null, docs);
// No need to do anything here, bulk import will be in the next step
}else{
util.log("There wasn't any data in the DB for this csv file: "+ configFile.importFileName);
var prepend = "being_imported__";
var path = generalConfig.sftpPathToImportFiles;
var oldName = prepend + configFile.importFileName;
var oldPath = path + oldName;
var newPath = path + "/archive/"+configFile.importFileName;
// This function also moves file
sftpHandler.renameFileOnSftp(oldPath, newPath, callback);
}
//MongoClient.readData(generalConfig.criterion, generalConfig.RecordModel, callback);
},
function(docs, callback) {
// If docs is not undefined, there were some documents/elements in DB for this file
if (docs){
// Do bulk import - This function is only passing a data to the next function in Waterfall
util.log("Going to post import definition.");
postImportDefinition(docs, configFile.importDefinition, configFile.importType, configFile, callback);
}else{
// Since there were no elements in DB for this file, continue processing next schedule config file
i++;
util.log("Recursively calling waterfall process due to missing elements in DB for this file. Iteration #"+i);
waterfallMain(configFiles, i);
return;
}
},
function(docs, uri, callback) {
util.log("Going to post the data to the: "+uri+", length - "+docs.length);
postData(docs, uri, callback);
},
// Passed docs to be able to change the status in the database for these items
function(docs, syncUri, callback) {
getSyncResponseInIntervals(docs, syncUri, callback);
}],
// The final callback function
function(err, docs) {
if (err) {
util.log(err);
switch (err.location){
case BULK_IMPORT_ERR_LOCATION:
// Update database by setting documents status attribute to failed
MongoClient.updateData(docs, "fail", generalConfig.RecordModel, waterfallRecursiveCallback);
break;
case NO_SUCH_SFTP_FILE_ERR_LOCATION:
waterfallRecursiveCallback();
break;
default:
// Update database by setting documents status to finished (at this point it shouldn't happen that docs obj is empty, as it is handled in previous functions in waterfall)
MongoClient.updateData(docs, "success", generalConfig.RecordModel, waterfallRecursiveCallback);
}
function waterfallRecursiveCallback(){
// If the loop is at it's last iteration, do the main process all over again in 1 minute
// This happens when there are no unprocessed files for the each of the configuration files
if (i == configFiles.length-1) {
util.log("Last iteration of config files. Going to run mainProcess() in 1 minute.");
setTimeout(function(){
mainProcess();
return;
}, 60000);
return;
}
// Recursively calling waterfall process again (this happens when there was no unprocessed file on the SFTP for given config - schedule config)
i++;
util.log("Recursively calling waterfall process. Iteration #"+i);
//util.log(JSON.stringify(configFiles));
waterfallMain(configFiles, i);
return;
}
}
当我调用sftpHandler.checkIfExists()
时,第一个函数就会出现问题。
我的checkIfExists()
:
SftpHandler.prototype.checkIfExists = function (path, fileName, callback) {
var c = new sftpJsClient();
console.log("Checking called from check if exists!!!!!!");
c.on('ready', function () {
console.log("C IS READY!!!!");
c.stat(path.concat(fileName), function(err, stats) {
if (err){
console.log("ERROR WHILE CHECKING"+err);
err.location = generalConfig.NO_SUCH_SFTP_FILE_ERR_LOCATION;
callback(err);
return;
}else{
console.log("Checking if file exists successfull."+JSON.stringify(stats));
// could rather use stats.isFile() here, but it's not necessary because if file doesn't exist it throws an error
callback(null);
return;
}
});
}).connect(this.sftpConnect);
};
输出日志:
5 Aug 09:46:50 - Running through all config files. Count: 3
5 Aug 09:46:50 - Checking if there is any processed file on the SFTP matching one in schedule config: processed__test1.csv
Checking called from check if exists!!!!!!
C IS READY!!!!
ERROR WHILE CHECKINGError: /E-drive/sftp/VismaReports/Test/QueueSystem/processed__test1.csv not found
5 Aug 09:46:51 - Error: /E-drive/sftp/VismaReports/Test/QueueSystem/processed__test1.csv not found
5 Aug 09:46:51 - Recursively calling waterfall process. Iteration #1
5 Aug 09:46:51 - Checking if there is any processed file on the SFTP matching one in schedule config: processed__test2.csv
Checking called from check if exists!!!!!!
5 Aug 09:46:51 - Waterfall process has ended, executing a mainProcess()
5 Aug 09:46:51 - Main process started.
5 Aug 09:46:51 - Running through all config files. Count: 3
5 Aug 09:46:51 - Checking if there is any processed file on the SFTP matching one in schedule config: processed__test1.csv
Checking called from check if exists!!!!!!
C IS READY!!!!
ERROR WHILE CHECKINGError: /E-drive/sftp/VismaReports/Test/QueueSystem/processed__test1.csv not found
5 Aug 09:46:52 - Error: /E-drive/sftp/VismaReports/Test/QueueSystem/processed__test1.csv not found
5 Aug 09:46:52 - Recursively calling waterfall process. Iteration #1
5 Aug 09:46:52 - Checking if there is any processed file on the SFTP matching one in schedule config: processed__test2.csv
Checking called from check if exists!!!!!!
5 Aug 09:46:52 - Waterfall process has ended, executing a mainProcess()
在输出中,您可能会看到每次调用该函数时都缺少log C IS READY !!!!
。我假设是因为c.on
是异步的,因此瀑布继续前进而不等待c.on
。
但是,如果我没有完成callback
,为什么会继续?
修改
当我注释掉c.on
函数时,瀑布挂起并等待回调被调用,正如预期的那样,但为什么当我取消注释而不等待回调时它会继续?
答案 0 :(得分:0)
正如official website所述:
运行函数的tasks数组,每个函数都通过它们 结果到阵列中的下一个。但是,如果任何任务通过了 错误到自己的回调,下一个函数没有执行,并且 主要的回调会立即调用错误。
您会看到导致
的日志function startTimer(duration, display) {
var timer = duration, minutes, seconds;
setInterval(function () {
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
timer = duration;
}
}, 1000);
}
window.onload = function () {
var fiveSec = 60 * koha, //If I make this 60 * 20 it works and there are 20 min to countdown
display = document.querySelector('#UItimer');
startTimer(fiveSec, display);
};
,您会看到错误
立即使用错误
调用主回调
答案 1 :(得分:0)
对我而言,它似乎是第二次调用,它试图读取processed__test2.csv
的那个,永远不会完成。似乎它在checkIfExists
中挂起该文件,并且永远不会调用sftp客户端的.on()
回调。
似乎还有很多事情正在进行,阅读两个不同的文件,每个文件两次。但是,日志显示Running through all config files. Count: 3
,这可能是一个错误,也可能是一些可疑的错误。
您是否可以尝试隔离问题:仅使用一个文件重复失败的方案。