首页 > 解决方案 > 即使使用了回调,函数也在异步函数之前执行

问题描述

当我将 LoadTask2 作为回调传递时,我会在完成读取文本文件之前执行 LoadTask2。可能是什么原因,如何在读取文本文件后执行 LoadTask2?

LoadTask1(LoadTask2);

function LoadTask1(LoadTask2) {
  let parEtask1Pending = document.getElementById('task1Status');
  parEtask1.replaceChild(loadingE, parEtask1Pending);
  currentIntervalId = setInterval(function() {
    readTextFile("file1.txt", getTextData);
  }, 2000);
  LoadTask2();
}

function LoadTask2() {
  console.log("Task2")
}

function readTextFile(file, callback) {
  console.log('Reading file..')
  var rawFile = new XMLHttpRequest();
  rawFile.open("GET", "textFiles/" + file, true);
  rawFile.onload = function() {

    if (this.status === 200) {
      getTextData(this.responseText);

    }

  }
  rawFile.send();
}

输出为:Task2->Reading file。

标签: javascript

解决方案


问题在这里:

function LoadTask1(LoadTask2) {
   let parEtask1Pending = document.getElementById('task1Status');
   parEtask1.replaceChild(loadingE, parEtask1Pending);
   currentIntervalId = setInterval(function() {
     readTextFile("file1.txt", getTextData);
   }, 2000);
   LoadTask2();
}

javascript 不会等到setInterval它完成。被setInterval执行并开始“并行”运行。

可能的解决方案是readTextFile像这样添加一个承诺:

  readTextFile = function(file) {
     return new Promise(function(resolve, reject){
        console.log('Reading file..')
        var rawFile = new XMLHttpRequest();
        rawFile.open("GET", "textFiles/" + file, true);
        rawFile.onload = function() {

        if (rawFile.status === 200) {
           resolve(rawFile.responseText);
        }
        rawFile.send();
     }
}

现在你可以.then()在你的函数上加上一个:

function LoadTask1(LoadTask2) {
   let parEtask1Pending = document.getElementById('task1Status');
   parEtask1.replaceChild(loadingE, parEtask1Pending);
   readTextFile("file1.txt").then(function(response){
      console.log("your response: " + response);
      LoadTask2();
   })     
}

还有另一种现代解决方案async/await。你也可以这样做:

 async function LoadTask1(LoadTask2) {
   let parEtask1Pending = document.getElementById('task1Status');
   parEtask1.replaceChild(loadingE, parEtask1Pending);
   const responseText = await readTextFile("file1.txt");
   console.log(responseText);
   LoadTask2();     
}

这应该可以,我还没有测试过。

此函数中还有一件事:

function readTextFile(file, callback) {
      console.log('Reading file..')
      var rawFile = new XMLHttpRequest();
      rawFile.open("GET", "textFiles/" + file, true);
      rawFile.onload = function() {

      if (this.status === 200) {
         getTextData(this.responseText);

      }

    }
 rawFile.send();
}

您实际上没有将任何内容传递回您的回调函数。您应该重命名getTextData(this.responseText)callback(this.responseText)然后在回调函数中执行 task2,如下所示:

function readTextFile(file, callback) {
      console.log('Reading file..')
      var rawFile = new XMLHttpRequest();
      rawFile.open("GET", "textFiles/" + file, true);
      rawFile.onload = function() {

      if (this.status === 200) {
         callback(this.responseText);

      }

    }
 rawFile.send();
}

function LoadTask1(LoadTask2) {
   let parEtask1Pending = document.getElementById('task1Status');
   parEtask1.replaceChild(loadingE, parEtask1Pending);
   readTextFile("file1.txt", function(response){
      console.log(response);
      LoadTask2();
   });

}

推荐阅读