回调总是异步的吗? [英] Are callbacks always asynchronous?

查看:330
本文介绍了回调总是异步的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个例子是JavaScript,因为这是我主要使用回调的地方。

This example is JavaScript, since that's where I'm using callbacks mostly. I want to understand how they work at a low level.

在下面的例子中,我希望一切顺利,并且回调发生在步骤3和步骤4之前。这对我来说是有意义的,因为一切都按顺序在单个执行线程上完成。没有骗局。唯一的事情是特别的,你已经传递一个函数到另一个函数。

In the example below, I'd expect everything to happen in order and "calling back" to occur after "step 3" and before "step 4." This makes sense to me, as everything is done in order on a single thread of execution. There's no trickery. The only thing that is sort of special is that you've passed a function to another function.

function main() {
  console.log("step 1");
  console.log("step 2");
  doSomething(myCallBack);
  console.log("step 4");
}

function doSomething(f) {
  accessTheDatabase(); // this could take a while
  console.log("step 3");
  f(); // done - now call back
}

function myCallBack() {
  console.log("calling back!");
}

如何使 doSomething 异步,以便步骤4可以在步骤3之前或与其并行执行?

How would you make doSomething asynchronous so that "step 4" can be executed before, or in parallel with, "step 3"?

我假设如果 doSomething 以某种方式异步调用,它必须在一个不同的线程,不是?如果是这样,当它完成,然后调用 myCallBack 回调发生在第二个线程或主线程?主线程,为什么第二个线程甚至需要一个指向回调函数的指针?线程间调用如何工作?

I assume that if doSomething were somehow called asynchronously, it would have to be on a diffferent thread, no? And if so, when it finishes and then calls myCallBack, does the callback happen on the second thread or on the main thread? If it happens on the main thread, why does the second thread even need a pointer to the callback function? How does the inter-thread call work?

推荐答案

WebWorkers ,浏览器中的JavaScript编程模型是纯单线程的。您可以使用 window.setTimeout 来使呼叫稍微有些异步:

WebWorkers aside, the JavaScript programming model in the browser is purely single-threaded. You can make your call somewhat asynchronous by using window.setTimeout:

window.setTimeout(doSomething, 0, myCallBack);

这有效地将调用 doSomething(myCallBack)到定时器队列,并且在0或更多毫秒过去之后,它将最终被调用。但是,与JavaScript中的所有异步调用一样,在调用任何异步回调之前,必须放弃执行上下文;也就是说,不会处理计时器队列(因此​​ doSomething(myCallBack)不会被调用),直到 main()

This effectively places the call doSomething(myCallBack) onto the timer queue, and after 0 or more milliseconds elapse, it will eventually get invoked. However, as with all asynchronous calls in JavaScript, you must relinquish the execution context before any asynchronous callbacks can be invoked; that is, the timer queue will not be processed (and therefore doSomething(myCallBack) will not be invoked) until your main() function finishes, assuming that is the end of your JavaScript.

这个 setTimeout 的一个不幸的后果 - 基本方法是 doSomething(myCallBack)不会被并行调用 console.log(step 4)。另一方面,请考虑 XMLHttpRequest.send ;在进行此调用后,您的其余JS可以在浏览器发出HTTP请求时继续执行。您的脚本需要在 onreadystatechange 处理程序可以执行之前完成执行,但大多数HTTP连接工作可以在JS执行时并行执行。

One unfortunate consequence of this setTimeout-based approach is that doSomething(myCallBack) doesn't get invoked in parallel alongside console.log("step 4"). On the other hand, consider XMLHttpRequest.send; after making this call, the rest of your JS can continue to execute while the browser issues the HTTP request. Your script does need to finish executing before the onreadystatechange handler can execute, but most of the HTTP connection work can happen in parallel while JS executes.

这篇关于回调总是异步的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆