在继续之前等待一个函数完成的正确方法?
我有两个JS函数。 一个叫另一个。 在调用函数中,我想调用另一个,等待该函数完成,然后继续。 所以,例如/伪代码:
function firstFunction(){ for(i=0;i<x;i++){ // do something } }; function secondFunction(){ firstFunction() // now wait for firstFunction to finish... // do something else };
我想出了这个解决scheme,但不知道这是否是一个聪明的方法去做。
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?
处理这种asynchronous工作的一种方法是使用callback函数,例如:
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的build议,你现在可以使用箭头函数来实现同样的事情。 例如:
firstFunction(() => console.log('huzzah, I\'m done!'))
看起来你错过了一个重要的观点:JavaScript是一个单线程执行环境。 让我们再看看你的代码,注意我已经添加了alert("Here")
:
var isPaused = false; function firstFunction(){ isPaused = true; for(i=0;i<x;i++){ // do something } isPaused = false; }; function secondFunction(){ firstFunction() alert("Here"); function waitForIt(){ if (isPaused) { setTimeout(function(){waitForIt()},100); } else { // go do that thing }; } };
你不必等待isPaused
。 当您看到“Here”警报时, isPaused
已经是false
了, firstFunction
将会返回。 这是因为你不能从for
循环中“产生”( // do something
),循环可能不会被打断并且必须首先完成(更多细节: Javascript线程处理和竞争条件 )。
也就是说,您仍然可以使firstFunction
内的代码stream成为asynchronous,并使用callback或承诺来通知调用者。 你必须放弃循环,并用if
来代替( JSFiddle )来模拟它:
function firstFunction() { var deferred = $.Deferred(); var i = 0; var nextStep = function() { if (i<10) { // Do something printOutput("Step: " + i); i++; setTimeout(nextStep, 500); } else { deferred.resolve(i); } } nextStep(); return deferred.promise(); } function secondFunction() { var promise = firstFunction(); promise.then(function(result) { printOutput("Result: " + result); }); }
另外,JavaScript 1.7引入了yield
关键字作为生成器的一部分。 这将允许在另外的同步JavaScript代码stream中“打”asynchronous空洞( 更多细节和示例 )。 但是,浏览器对生成器的支持目前仅限于Firefox和Chrome,AFAIK。