【问题标题】:Trying to wait for list to be populated before iterating through it NodeJS尝试在迭代之前等待列表被填充 NodeJS
【发布时间】:2019-08-26 12:06:01
【问题描述】:

我有一些代码可以获取上传的文件,执行它并获取输出。然后,它将此输出与预期输出进行比较,以检查脚本是否按预期执行。

我现在正在尝试改进此功能,以便上传的文件将运行多次,每次都根据不同的预期输出或“测试用例”进行检查。然后我想将“正确”或“不正确”推送到结果数组,以便我可以在最后检查该数组并检查是否有任何“不正确”(文件是否未通过任何测试用例)。

  • 我只尝试了每个函数中的回调。
  • 我已尝试在 getArray 上使用 await 和 async,如下所示
  • 同时使用回调和异步。

这是调用要创建的数组的父函数代码,并希望在创建后对其进行迭代。

var resultsArr = await getResults(file.name, files.length, markerDir);
//file.name is the name from the uploaded file object
//files.length is the number of subdirectories (number of testcases to run against)
//markerDir is the str path to where these testcases are stored

if (resultsArr){
   for(var i=0;i<resultsArr.length;i++) {

      if (resultsArr[i] == "incorrect"){                    
         checkForMarkerCb('incorrect'); //Calls back to frontend to
         break;                         //display result on web app
      }

      else if (i+1 == resultsArr.length) {
         checkForMarkerCb('correct');
      }
   }
}

下面是上面调用的getResults函数里面

for(var i=1; i<=fileLength; i++) {
   var sampleOut = markerDir + '/test' + i + '/stdout.txt';

   //Grab expected stdout.txt
   var markerOut = fs.readFileSync(sampleOut, 'utf-8', function(err){
      if (err){
         throw err;
      };
   });

   //Run the file and grab the output
   executeFile(filename, function(fileOut){

      //Compare output with sample stdout
      if (markerOut == fileOut){
         resultsArr.push('correct');
      }

      else {
         resultsArr.push('incorrect');
      }
   });
}

//If results array has a response for each testcase
if (resultsArr.length == fileLength) {
   return resultsArr;
}

按要求执行executeFile():


function executeFile(filename, execFileCb){
   //pathToUpload is a str path to where the upload is stored

   const child = execFile('python', [pathToUpload], (err,stdout,stderr) => {
      if (err) {
         throw err;
      }

      execFileCb(stdout); //Callback with output of file
   });
}
function executeFileAsync(filename) {
    return new Promise(function(resolve,reject){
        executeFile(filename, function(err, data){
            if (err !== null) reject(err);

            else resolve(data);

        });
    });
}

在 getResults() 中使用

调用
var fileOut = await executeFileAsync(filename)
  • 调用getResults()的初始函数。
  • getResults():获取每个目录的路径并调用将比较输出的结果推送到结果数组中。
  • executeFile():使用 'child_process' 运行文件并使用输出回调。

我希望代码等待 getResults 返回 resultsArr,以便 for 循环可以遍历并检查任何“不正确”。相反,getResults 在填充 resultsArr 之前返回。

使用一些日志记录,我看到用于检查 markerOut == fileOut 的代码在 getResults() for 循环已经完成后执行。我尝试将对 executeFile() 的调用设置为类似于 getResults() 的调用方式的异步/等待,但仍然没有变化。

我可能没有正确使用异步/回调,非常感谢任何帮助。

【问题讨论】:

  • 您能告诉我们您是如何尝试在getResults 中使用async/await 的吗?尤其是您如何转换 executeFile 以使其返回承诺?
  • @Bergi 我将 getResults 声明为“异步函数 getResults(filename, fileLength, markerDir) 当我尝试为 executeFile 执行此操作时,我让它返回输出而不是使用回调。var fileOut = await executeFile(filename) ..类似于上面代码中调用getResults的方式。
  • edit您的问题显示代码。还要展示executeFile 的实现,这似乎很重要。请注意,您不能简单地 return 异步结果,您需要返回一个 Promise 并稍后实现它。
  • @Bergi 进行了一些编辑,我对 promises/callbacks/async 感到困惑,并认为使用 async/await 是使用 promise 的替代方法。有没有办法用 Promises 解决这个问题?
  • 您只能将async/await 与promise 一起使用,不能代替它们。 await 是围绕 .then() 调用的语法糖,但承诺仍然存在。你需要make your executeFile function return a promise

标签: javascript arrays node.js asynchronous callback


【解决方案1】:

您的executeFileAsync 函数当前调用executeFile 并带有一个回调,该回调需要两个参数,但executeFile 调用此execFileCb 时总是只带有一个参数,这被解释为错误。它也不应该在异步回调中使用throw

相反,将它们合并为一个函数:

function executeFile(filename) {
  return new Promise(function(resolve,reject){
    //pathToUpload is a str path to where the upload is stored

    const child = execFile('python', [pathToUpload], (err,stdout,stderr) => {
      if (err) reject(err);
      else resolve(stdout); //Callback with output of file
    });
  });
}

【讨论】:

  • 非常感谢!最后让它正确地等待数组被填充,我现在理解了 Promises。真的很感激!
猜你喜欢
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
相关资源
最近更新 更多