在继续之前等待一个函数完成的正确方法?

我有两个JS函数。一个调用另一个。在调用函数中,我想调用另一个函数,等待该函数完成,然后继续。因此,例如/伪代码:

function firstFunction(){
    for(i=0;i<x;i++){
        // do something
    }
};

function secondFunction(){
    firstFunction()
    // now wait for firstFunction to finish...
    // do something else
};

我想出了这个解决方案,但不知道这是否是一种明智的方法。

var isPaused = false;

function firstFunction(){
    isPaused = true;
    for(i=0;i<x;i++){
        // do something
    }
    isPaused = false;
};

function secondFunction(){
    firstFunction()
    function waitForIt(){
        if (isPaused) {
            setTimeout(function(){waitForIt()},100);
        } else {
            // go do that thing
        };
    }
};

这是合法的吗?有没有更优雅的方法来处理它?也许使用jQuery?


答案 1

处理此类异步工作的一种方法是使用回调函数,例如:

function firstFunction(_callback){
    // do some asynchronous work
    // and when the asynchronous stuff is complete
    _callback();    
}

function secondFunction(){
    // call first function and pass in a callback function which
    // first function runs when it has completed
    firstFunction(function() {
        console.log('huzzah, I\'m done!');
    });    
}

根据@Janaka Pushpakumara的建议,您现在可以使用箭头函数来实现相同的目标。例如:

firstFunction(() => console.log('huzzah, I\'m done!'))


更新:我很久以前就回答了这个问题,并且真的很想更新它。虽然回调是绝对好的,但根据我的经验,它们往往会导致代码更难以阅读和维护。但是,在某些情况下,我仍然使用它们,例如将正在进行的事件等作为参数传递。此更新只是为了强调替代方案。

此外,原始问题没有特别提到异步,所以如果有人感到困惑,如果你的函数是同步的,它会在调用时阻塞。例如:

doSomething()
// the function below will wait until doSomething completes if it is synchronous
doSomethingElse()

如果像暗示的那样,函数是异步的,那么我今天处理所有异步工作的方式是异步/等待。例如:

const secondFunction = async () => {
  const result = await firstFunction()
  // do something else here after firstFunction completes
}

IMO,async/await使您的代码比直接使用承诺(大多数时候)更具可读性。如果您需要处理捕获错误,请将其与try/catch一起使用。在这里阅读更多信息: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function .


答案 2

使用异步/等待 :

async function firstFunction(){
  for(i=0;i<x;i++){
    // do something
  }
  return;
};

然后在其他函数中使用 await 来等待它返回:

async function secondFunction(){
  await firstFunction();
  // now wait for firstFunction to finish...
  // do something else
};