简体   繁体   English

javascript 中的异步行为和回调

[英]Asynchronous behavior and callbacks in javascript

I was hopping around various websites but couldn't understand how callbacks make javascript asynchronous.我在各种网站上跳来跳去,但无法理解回调如何使 javascript 异步。 To my understanding callbacks are any functions that are called inside one another function.据我所知,回调是在另一个函数内部调用的任何函数。 It is just another function call.这只是另一个函数调用。 How does javascript know which functions to execute asynchronously and how it handles under the hood? javascript 如何知道异步执行哪些函数以及它如何在后台处理?

Sample Code 1示例代码 1

function A(x){
//...code for func A;
}

function B(y){
//...code for func B;
A(2);  // 2 for example
}

Sample Code 2:示例代码 2:

function A(x){
//...code for func A;
}

function B(y,A){
//...code for func B;
A(2);  // 2 for example
}

Kindly explain how javascript differentiates between these two pieces codes?请解释javascript如何区分这两个代码?

I was hopping around various websites but couldn't understand how callbacks make javascript asynchronous.我在各种网站上跳来跳去,但无法理解回调如何使 javascript 异步。

They do not.他们不。 The code you posted, by itself, isn't asynchronous.您发布的代码本身不是异步的。 Callbacks are not an asynchronous pattern on their own (as an example look at Array.prototype.forEach ) but they are used as one way to handle asynchronous behavior.回调本身不是异步模式(例如查看Array.prototype.forEach ),但它们被用作处理异步行为的一种方式。

To my understanding callbacks are any functions that are called inside one another function.据我所知,回调是在另一个函数内部调用的任何函数。 It is just another function call.这只是另一个函数调用。

Basically, except that they are also passed as arguments.基本上,除了它们也作为参数传递。 When we say a callback in javascript, we usually mean functions that are passed down from one function to another and that call back the initial function, hence the name.当我们在 javascript 中说回调时,我们通常指的是从一个函数传递到另一个函数并回调初始函数的函数,因此得名。 In general however, a callback is just a piece of executable code, that is passed as an argument to other code.然而,一般来说,回调只是一段可执行代码,它作为参数传递给其他代码。


The main difference between the two samples you provided here is how they obtain access to each other , not whether they are asynchronous or synchronous.您在此处提供的两个示例之间的主要区别在于它们如何获取彼此的访问权限,而不是它们是异步的还是同步的。

Both samples contain synchronous code but only one of them contains a callback:两个示例都包含同步代码,但其中只有一个包含回调:

  • Sample 1: function B obtains access to A via its global scope.示例 1:函数 B 通过其全局作用域获得对 A 的访问。 not callback不回调
  • Sample 2: function B obtains access to A via its arguments: callback示例 2:函数 B 通过其参数获取对 A 的访问权:回调

For sample 1, no matter how you call B(y) , since it always invokes A internally, it doesn't callback anything, it just calls another function.对于示例 1,无论您如何调用B(y) ,由于它始终A内部调用A ,因此它不会回调任何内容,它只会调用另一个函数。

For sample 2, you can call B(y, A) or B(y, C) with another function C(){} and it will call back whichever function you passed into it.对于示例 2,您可以使用另一个function C(){}调用B(y, A)B(y, C) ,它会回调您传递给它的任何函数。

Perhaps it would be less confusing if you renamed the functions like this:如果您像这样重命名函数,也许就不那么令人困惑了:

Sample Code 1示例代码 1

function A(x){
  //...code for func A;
}

function B(y){
  //...code for func B;
  A(2);  // calls above A()
}

Sample Code 2:示例代码 2:

function A(x){
  //...code for func A;
}

function B(y, callback){
  //...code for func B;
  callback(2);  // calls whichever callback you pass in
}

Demonstration examples演示示例

 // EXAMPLE 1 function A1() { console.log('A1 is called'); } function B1() { console.log('B1 is called'); A1(2); // calls above A() } B1(); // Output: // B1 is called // A1 is called B1('whatever'); // Output: // B1 is called // A1 is called // EXAMPLE 2 function A2() { console.log('A2 is called'); } function B2(callback) { console.log('B2 is called'); callback(); // calls whichever callback you pass in } // We can callback to any function (but not no function) B2(A1); // Output: // B2 is called // A1 is called B2(A2); // Output: // B2 is called // A2 is called B2(); // Output: // B2 is called // Uncaught TypeError: callback is not a function (because we didn't pass anything as the callback)

Sample Code 1 as async示例代码 1 作为异步

Now let's demonstrate some asynchronous behavior with a common tool, the setTimeout function.现在让我们使用常用工具setTimeout函数演示一些异步行为。 I will use sample code 1 because it doesn't contain any callback code, to also show how callbacks tie into async behavior.我将使用示例代码 1,因为它不包含任何回调代码,以展示回调如何与异步行为相关联。

function A(x){
  //...code for func A;
}

function B(y){
  //...code for func B;
  setTimeout(A, 3000); // call A after 3 seconds
}

B();

In the code above, function A is passed as a callback to function setTimeout .在上面的代码中,函数A作为回调传递给函数setTimeout That means that setTimeout definition would conceptually look something like:这意味着setTimeout定义在概念上看起来像:

function setTimeout(callback, duration) {
 // call callback after duration milliseconds
}

What happens when you execute the above code is that the lexical parser first hoists the functions to the top of the code .执行上述代码时会发生什么,词法解析器首先将函数提升到代码的顶部 Then the invocation of B() happens, followed by all synchronous code afterwords because JS is single-threaded.然后调用B() ,然后是所有同步代码后记,因为 JS 是单线程的。 This means that A cannot be executed until the thread that called setTimeout() has terminated.这意味着在调用setTimeout()的线程终止之前不能执行A

Only when all synchronous code is finished and 3 seconds have passed will you get invocation of A() .只有当所有同步代码都完成并且 3 秒过去了,你才会调用A()

In general, anytime you write some code to react when data from the server is received or when the user clicks the mouse, that code is asynchronous.通常,无论何时您编写一些代码以在接收到来自服务器的数据或用户单击鼠标时做出反应,该代码都是异步的。 It gets executed when something happens .它在发生某些事情时被执行。

As @Pointy pointed out in the comments, this asynchronous behavior isn't a direct feature of JavaScript on its own.正如@Pointy在评论中指出的那样,这种异步行为本身并不是 JavaScript 的直接特性。 It usually comes from interaction with the system JS is running in and the events that system sends (user interacting with the browser or the operating system interacting with something like NodeJS)它通常来自与运行 JS 的系统的交互以及系统发送的事件(用户与浏览器交互或操作系统与 NodeJS 之类的交互)

Asynchronous behavior of Javascript Javascript 的异步行为

 <script> var message = ''; function writeToDocument( string ) { window.message += '<br/>'+string; document.write(window.message); } function A() { var string = 'A is Called'; setTimeout( function(){writeToDocument(string)},3000); } function B() { writeToDocument('B is Called'); } A(); //We are calling A first; B(); </script>

OUTPUT输出

B is Called
A is Called

even though we called A first, B gets called first, Javascript is Asynchronous即使我们先调用了 A,也先调用了 B,但Javascript 是异步的

Synchronous behavior of PHP PHP 的同步行为

<?php

function writeToDocument( $string )
{
    echo '<br/>'.$string; 
}

function A()
{
    sleep(3000);
    writeToDocument('A is Called');
}

function B()
{
    writeToDocument('B is Called');
}

A();
B();

OUTPUT输出

A is Called
B is Called

B will not be called unless A is finished executing, PHP is Synchronous除非 A 执行完毕,否则不会调用 B, PHP 是同步的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM