开发者

Are callbacks always asynchronous? [duplicate]

This question already has answers here: Are all javascript callbacks asynchronous? If not, how do I know which are? (5 answers) Closed 6 years ago.

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

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");
  consol开发者_JS百科e.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!");
}

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

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 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);

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.

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.


Hmmm.. something looks wrong (I have done v little JavaScript): you pass myCallBack to the function doSomething() but you dont call it back!? You would have to have a call to f() inside doSomething() or pass it to another function which will call it back once your long operation is complete.. And no callbacks are not inherently asynchronous - in your case you are running it all on the same thread (even if accessTheDatabase() is asynchronous in which case it would immediately return!) - so it will still go Step1, Step2, Step3, Step4. I beleive you want:

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

function doSomething(f) {
  accessTheDatabase(f); // assuming this is an asynchronous operation and calls the callback f once done
}

function myCallBack() {
   console.log("step 3");
}

In answer to the second part of your question: the callback would be run on which ever thread you are calling it from - to run a callback on another thread you would have to join() that thread first then invoke() or begininvoke() the callback - though there may already be some built in way to dispatch your callback onto a queue of things to be run on the thread you want to run it on (often the case with UI threads) NOTE: It may already be that accessTheDatabase() does run the callback on the thread that called it - using one of the afore mentioned methods...


You would need multiple threads of execution to do this, which I do not believe you can do in Javascript (although correct me if I'm wrong). However if you were writing a C/C++ program, look at the pthreads package (or libdispatch on Mac OS X 10.6).

Edit: a Google search for "threads javascript" turns up some possibly interesting results.


Using callbacks the way you are (function declaration name or function expression variable name as an argument to another function), they are synchronous. To make them asynchronous, you can wrap them in a setTimeout.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜