JavaScript(asynchronous)如何确定在继续之前要“等待”什么?

最近我正在使用JavaScript,我试图弄清楚解释器是如何决定何时“等待”以及何时asynchronous移动到下一行代码的。

以这两个代码示例。 阅读我的意见,我的困惑。

1:

function doAThing(thing, callback) { var someBoolean; if ( !thing ) { someBoolean = true; } else { someBoolean = false; } // Calling the callback function only happens *after* the above if statement, // meaning the interpreter waits instead of just calling it immediately? callback(someBoolean); } 

2:

 function doOtherThing(thing, callback) { var someBoolean; // Some fake ORM, querying a fake DB with a where clause of thing Model.find().where({ someProperty: thing }).exec(function(err, results){ if ( results ) { someBoolean = true; } else { someBoolean = false; } }); // Calling the callback function happens *immediately* and does NOT wait for // someBoolean to get a value inside the ORM query above before it proceeds, // so the callback function is given an undefined value for someBoolean callback(someBoolean); } 
  • 在示例1中,为什么/如何在调用callback函数之前等待if语句被完全执行?
  • 你如何确定JavaScript将“等待”什么东西,而不是等待什么呢?
  • 什么是一些策略来处理这个控制stream在本地JavaScript更优雅,没有使用库,如Q,asynchronous等?

我可能有一些这个术语错了,随时纠正我。 我在这里尝试了解它,并欣赏任何build议。 我也有兴趣阅读任何有关JavaScriptasynchronous的资源,但不知道在哪里看。

干杯!

编辑:我明白,在例#2我可以“强制”callback只有当someBoolean通过将callback调用放在ORM查询结束时有一个值。 但是,这往往很容易变得笨拙。 这是例子#3:

 function doSomething(thing, callback) { // Some fake ORM, querying a fake DB with a where clause of thing Model.find().where({ someProperty: thing }).exec(function(err, results){ ModelTwo.find().where({ somethingElse: thing }).exec(function(err, results){ ModelThree.find().where({ somethingElse: thing }).exec(function(err, results){ ModelFour.find().where({ somethingElse: thing }).exec(function(err, results) { // Tons and tons of nesting, getting ever-more-confusing // and pushing my code further to the right.... callback(); }); }); }); }); } 

这是一个非常复杂的例子,但在使用Node之前,我碰到过类似的情况。 当我必须在一个数据库上运行多个查询或多次与一些外部服务交互时,它会非常快速地混乱,最后我需要调用callback函数。

我想我的问题是:在原生的JavaScript,有没有更好的方法来避免所有这种嵌套废话,或者我应该只使用一个承诺库,如Q或asynchronous?

我想在本地JS中更像这样的控制stream:

 function doAThing(thing, callback) { var bool1, bool2, bool3, bool4; SomeLib.someAction().exec(function(err, results){ bool1 = false; }); SomeLib.someOtherAction().exec(function(err, results){ bool2 = true; }); SomeOtherLib.action().exec(function(err, results){ bool3 = false; }); SomeOtherLib.delete().exec(function(err, results){ bool4 = true; }); // I'd like this only to be called when the above 4 actions are complete, // **without** nesting all of the actions together and calling the // callback at the end of the last one. As far as I understand it now... // I will need a library like async or q in order to have a // control flow like this? callback(bool1, bool2, bool3, bool4); } 

错误,JavaScript是完全同步的。 您的代码示例中没有任何代表解释器的“决定”涉及是否等待; 没有涉及等待。 两个示例中的每个语句都将按顺序执行,而不会中断。 有些function阻断,有些function不能,但是这不是解释器。

 if ( !thing ) { someBoolean = true; } else { someBoolean = false; } // Calling the callback function only happens *after* the above if statement, // meaning the interpreter waits instead of just calling it immediately? callback(someBoolean); 

如果function阻塞,则阻塞。 你不必担心,你的代码按照从上到下的顺序执行。

 var someBoolean; // Some fake ORM, querying a fake DB with a where clause of thing Model.find().where({ someProperty: thing }).exec(function(err, results){ if ( results ) { someBoolean = true; } else { someBoolean = false; } }); // Calling the callback function happens *immediately* and does NOT wait for // someBoolean to get a value inside the ORM query above before it proceeds, // so the callback function is given an undefined value for someBoolean callback(someBoolean); 

这是正确的。 您应该在传递给ORM的函数中调用callback 。 当结果准备就绪时,您需要调用callback函数,这就是callback的全部要点。 你的函数不需要立即调用它的callback函数,这样就会失败。

你如何确定JavaScript将“等待”什么东西,而不是等待什么呢?

通过阅读文件。 如果它接受一个callback函数,这可能是如何将一个值传递给你的代码。

什么是一些策略来处理这个控制stream在本地JavaScript更优雅,没有使用库,如Q,asynchronous等?

… 你什么意思? 你传递一个callback函数。 如果你想得到比这更复杂的,你应该使用一个库,如Q,asynchronous等

阅读事件是如何工作的,因为在js中asynchronous的东西都涉及事件和事件监听器。 它只是传递callback作为参数,然后在函数内部调用它们。

asynchronous代码是这样工作的:

  • 一个函数注册一个事件监听器和一个事件处理器,然后完成并返回
  • 当它监听的事件触发时,事件处理程序会到达在单个线程中执行的代码列表的末尾,并按它们发生的顺序依次执行。

想象一下,你所有的代码都是作为一个单线程运行的,一条执行线。 你在代码中注册的任何事件监听器在init代码中的所有其他事件完成之后会被执行,它们之间的任何地方都无法执行,就像两个事件不能同时处理一样。

你所做的所有例子都是围绕着一个angular度引导线程,围绕一个函数进行漏斗,也许会产生一个结,但是他们并没有真正地“爆发”这个线程。 如果你另一方面只是使用

 setTimeout(yourCallback,0); 

那么你突然asynchronous。 你的callback将进入等待线的末尾,将不得不等待,直到你的当前代码的每一个部分被执行,并且“没有别的事情可以做”,这样它可以进入下一个在线等待或空闲,等待事件发生。