javascript中的异步行为和回调

时间:2016-04-25 18:04:38

标签: javascript function asynchronous callback

我在各种网站上跳来跳去,却无法理解回调如何让javascript异步。据我所知,回调是在另一个函数内部调用的任何函数。这只是另一个函数调用。 javascript如何知道异步执行哪些函数以及它如何处理?

示例代码1

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

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

示例代码2:

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

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

请解释javascript如何区分这两段代码?

2 个答案:

答案 0 :(得分:1)

  

我在各种网站上闲逛,但无法理解回调如何使javascript异步。

他们没有。您发布的代码本身并不是异步的。回调本身不是异步模式(例如Array.prototype.forEach),但它们被用作处理异步行为的一种方式。

  

据我所知,回调是在另一个函数内部调用的任何函数。这只是另一个函数调用。

基本上,除了它们也作为参数传递。当我们在javascript中说回调时,我们通常意味着从一个函数传递到另一个函数的函数以及回调初始函数,因此名称。但是,一般来说,回调只是一段可执行代码,它作为参数传递给其他代码。

您在此处提供的两个示例之间的主要区别是他们如何获得彼此的访问,而不是它们是异步还是同步。

两个示例都包含同步代码,但只有一个包含回调:

  • 示例1:功能B通过其全局范围获得对A的访问。 不回拨
  • 示例2:功能B通过其参数获得对A的访问:回调

对于示例1,无论您如何调用B(y),因为总是在内部调用A,它不会回调任何内容,它只是调用另一个函数

对于示例2,您可以使用另一个B(y, A)来呼叫B(y, C)function C(){},它会回拨您传入其中的任何功能。

如果你重命名这样的函数,也许不那么令人困惑:

示例代码1

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

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

示例代码2:

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

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

演示示例



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




示例代码1 as async

现在让我们用一个通用工具setTimeout函数演示一些异步行为。我将使用示例代码1,因为它不包含任何回调代码,以显示回调如何与异步行为相关联。

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

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

B();

在上面的代码中,函数A作为回调传递给函数setTimeout。这意味着setTimeout定义在概念上看起来像:

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

执行上述代码时会发生的是词法解析器首先hoists the functions to the top of the code。然后调用B(),然后是所有同步代码后缀,因为JS是单线程的。 这意味着在调用A的线程终止之前,setTimeout()无法执行。

只有当所有同步代码完成并且已经过了3秒后,才会调用A()

通常,无论何时编写一些代码来响应来自服务器的数据或用户单击鼠标时,该代码都是异步的。当事情发生时,它会被执行

正如 @Pointy 在评论中指出的,这种异步行为本身并不是JavaScript的直接特性。它通常来自与JS运行的系统的交互以及系统发送的事件(用户与浏览器交互或操作系统与NodeJS之类的交互)

答案 1 :(得分:0)

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>

<强>输出

B is Called
A is Called

即使我们首先调用A,B首先调用, Javascript是异步的

PHP的同步行为

<?php

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

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

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

A();
B();

<强>输出

A is Called
B is Called

除非A完成执行,否则不会调用B, PHP是同步