所有的javascript回调都是异步的吗?如果没有,我怎么知道哪些是?

时间:2022-08-13 07:17:29

I'm curious as to whether all javascript callbacks are asynchronous, or whether that is the case only in certain situations. Also, I'm sure what makes javascript code asynchronous (or ways to use asynchronous javascript) differ between the browser and nodejs, so I'd like to know in each situation what constitutes real asynchronous javascript.

我很好奇所有的javascript回调是否都是异步的,或者只是在某些情况下是这种情况。此外,我确定是什么让javascript代码异步(或使用异步javascript的方法)在浏览器和nodejs之间有所不同,所以我想知道在每种情况下什么构成真正的异步javascript。

I'm under the impression that in the following scenarion, I'm not actually writing asynchronous code.

我的印象是,在下面的场景中,我实际上并没有编写异步代码。

function addOne(value){
  value = value + 1;
  return value;
}

function simpleMap(values, callback){
  for(i = 0; i < values.length; i++){
    val = values[i];
    val = callback(val);
    values[i] = val;
  }
  return values;
}

newValues = simpleMap([1,2,3], addOne);

However, for example, I know that jQuery's AJAX functions are truly asynchronous (not taking in to account the promises which are now available). What is it that make jQuery's AJAX asynchronous? Is it as simple that it involves XHR requests, and in the browser, all XHR requests are asynchronous?

但是,例如,我知道jQuery的AJAX函数是真正异步的(没有考虑到现在可用的承诺)。是什么让jQuery的AJAX异步?是否涉及XHR请求这么简单,在浏览器中,所有XHR请求都是异步的?

I have the same question for the nodejs environment. Can something in node only be asynchronous if it involves something like file i/o, process.nextTick, setTimeout, or setInterval? Why when I do something like a database call with mongodb/mongoose, is that asynchronous? What's going on behind the scenes that's making it so?

我对nodejs环境有同样的问题。节点中的某些东西只有在涉及文件i / o,process.nextTick,setTimeout或setInterval之类的东西时才能是异步的吗?为什么当我使用mongodb / mongoose进行数据库调用时,是异步的?幕后发生了怎样的事情呢?

Are asynchronous "situations" predetermined by the environment? Or is there some way to make one's own function truly asynchronous without leveraging very specific functions of the environment (such as xhr, file io in node, process.nexttick, etc)?

异步“情况”是否由环境预先确定?或者是否有一些方法可以使自己的函数真正异步而不利用环境的非常特定的函数(例如xhr,节点中的文件io,process.nexttick等)?

4 个解决方案

#1


35  

I'm curious as to whether all javascript callbacks are asynchronous

我很好奇所有的javascript回调是否都是异步的

No. For instance, the callback used by Array#sort is not asynchronous, nor is the one used by String#replace.

不可以。例如,Array#sort使用的回调不是异步的,也不是String#replace使用的回调。

The only way you know whether a callback is asynchronous is from its documentation. Typically, ones involving requests for external resources (ajax calls, for instance) are asynchronous, and others may or may not be.

您知道回调是否异步的唯一方法是来自其文档。通常,涉及对外部资源(例如,ajax调用)的请求的是异步的,而其他可能是也可能不是。

However, for example, I know that jQuery's AJAX functions are truly asynchronous...

但是,例如,我知道jQuery的AJAX函数是真正的异步...

Not necessarily, as currently jQuery still has the async flag which you can set false to force a synchronous request. (It's not a good idea, and they're going to remove that, but you can. jQuery passes the flag to the underlying browser object which provides the synchronous/asynchronous behavior.)

不一定,因为当前jQuery仍然具有异步标志,您可以将其设置为false以强制执行同步请求。 (这不是一个好主意,他们会删除它,但你可以.jQuery将标志传递给提供同步/异步行为的底层浏览器对象。)

What is it that make jQuery's AJAX asynchronous?

是什么让jQuery的AJAX异步?

The browser. jQuery's ajax calls use the XMLHttpRequest object (or in certain situations, a script element), which defaults to asynchronous operation provided by the browser.

浏览器。 jQuery的ajax调用使用XMLHttpRequest对象(或在某些情况下,脚本元素),默认为浏览器提供的异步操作。

Or is there some way to make one's own function truly asynchronous without leveraging very specific functions of the environment...

或者有没有办法让自己的功能真正异步,而不利用环境的非常具体的功能......

Until recently, no. Up through the 5th edition specification, JavaScript the language was basically silent on the entire concept of threads and asynchronicity; it was only when you got into environments that it came up. The only way to make something asynchronous was to use a host-provided function, such as nextTick (or any of the various operations that completes asynchronously) on NodeJS or setTimeout on browsers.

直到最近,没有。通过第5版规范,JavaScript语言基本上对线程和异步性的整个概念保持沉默;只有当你进入环境时它才出现。使异步生成的唯一方法是使用主机提供的函数,例如在NodeJS上的nextTick(或异步完成的任何各种操作)或浏览器上的setTimeout。

In the ECMAScript 6th edition specification in June 2015, they introduced promises into the language. The callbacks hooked up to an ES6 promise via then and such are always invoked asynchronously (even if the promise is already settled when the callback is attached), and so JavaScript has asynchronicity at a language level now. So if you implement your function so that it returns a promise rather than accepting a callback, you'll know that the then callbacks hooked up to it will be triggered asynchronously.

在2015年6月的ECMAScript第6版规范中,他们将承诺引入该语言。通过那时回调连接到ES6承诺,并且总是异步调用(即使在附加回调时承诺已经解决),因此JavaScript现在在语言级别具有异步性。因此,如果您实现您的函数以便它返回一个promise而不是接受一个回调,那么您将知道连接到它的then回调将异步触发。

#2


8  

To create your own asynchronous functions you have to make use of other asynchronous functions which may be provided by the interpreter.

要创建自己的异步函数,必须使用解释器可能提供的其他异步函数。

This code for example defines a function "addKeyHandler" which is asynchronous. But that only works because document.onKey is called asynchronously by the JS engine. The JavaScript engine is able to provide asynchronous functionality because the operating system provides such functionality which is then used by JS. The OS in turn can only provide async functionality because the hardware provides it (called hardware interrupts).

例如,该代码定义了一个异步的函数“addKeyHandler”。但这只能起作用,因为JS引擎异步调用document.onKey。 JavaScript引擎能够提供异步功能,因为操作系统提供了这样的功能,然后由JS使用。操作系统反过来只能提供异步功能,因为硬件提供它(称为硬件中断)。

However if the OS and hardware didn't provide any async functions it would still be possible to write a JS interpreter. But it would have to use an infinite loop and check in each iteration if any events occured and then invoke the appropriate callbacks. That would mean the CPU would always be under full load.

但是,如果操作系统和硬件没有提供任何异步功能,那么仍然可以编写JS解释器。但它必须使用无限循环并检查每次迭代是否发生任何事件,然后调用适当的回调。这意味着CPU总是处于满负荷状态。

var keyCallbacks = [];

var addKeyHandler = function(f) {
  keyCallbacks.push(f);
};

document.onkeypress = function(e) {
  keyCallbacks.forEach(function(f) {
      f(e);
  });
};

addKeyHandler(function(e) {
    console.log(String.fromCharCode(e.charCode));
});

#3


6  

Callbacks that you call yourself are regular function calls, which are always synchronous.

您自己调用的回调是常规函数调用,它们始终是同步的。

Certain native APIs (eg, AJAX, geolocation, Node.js disk or network APIs) are asynchronous and will execute their callbacks later in the event loop.

某些本机API(例如,AJAX,地理定位,Node.js磁盘或网络API)是异步的,稍后将在事件循环中执行其回调。

If you call a callback synchronously from within an async callback, it will end up being async too.

如果从异步回调中同步调用回调,它也将最终异步。

#4


0  

Simply taking a callback doesn't make a function asynchronous. There are many examples of functions that take a function argument but are not asynchronous, for example, Array's forEach.

简单地进行回调不会使函数异步。有许多函数的例子采用函数参数但不是异步的,例如,Array的forEach。

For a function to be asynchronous it needs to perform an asynchronous operation. Ways of introducing asynchronicity can be

对于异步函数,它需要执行异步操作。引入异步性的方法可以是

  • timer functions setTimeout, setInterval
  • timer函数setTimeout,setInterval
  • special functions nextTick, setImmediate
  • 特殊功能nextTick,setImmediate
  • performing I/O (listening to network, querying a database, reading or writing from a resource)
  • 执行I / O(侦听网络,查询数据库,从资源读取或写入)
  • subscribing to an event
  • 订阅活动

According to article "Does taking a callback make a function asynchronous?"

根据文章“采取回调是否使函数异步?”

#1


35  

I'm curious as to whether all javascript callbacks are asynchronous

我很好奇所有的javascript回调是否都是异步的

No. For instance, the callback used by Array#sort is not asynchronous, nor is the one used by String#replace.

不可以。例如,Array#sort使用的回调不是异步的,也不是String#replace使用的回调。

The only way you know whether a callback is asynchronous is from its documentation. Typically, ones involving requests for external resources (ajax calls, for instance) are asynchronous, and others may or may not be.

您知道回调是否异步的唯一方法是来自其文档。通常,涉及对外部资源(例如,ajax调用)的请求的是异步的,而其他可能是也可能不是。

However, for example, I know that jQuery's AJAX functions are truly asynchronous...

但是,例如,我知道jQuery的AJAX函数是真正的异步...

Not necessarily, as currently jQuery still has the async flag which you can set false to force a synchronous request. (It's not a good idea, and they're going to remove that, but you can. jQuery passes the flag to the underlying browser object which provides the synchronous/asynchronous behavior.)

不一定,因为当前jQuery仍然具有异步标志,您可以将其设置为false以强制执行同步请求。 (这不是一个好主意,他们会删除它,但你可以.jQuery将标志传递给提供同步/异步行为的底层浏览器对象。)

What is it that make jQuery's AJAX asynchronous?

是什么让jQuery的AJAX异步?

The browser. jQuery's ajax calls use the XMLHttpRequest object (or in certain situations, a script element), which defaults to asynchronous operation provided by the browser.

浏览器。 jQuery的ajax调用使用XMLHttpRequest对象(或在某些情况下,脚本元素),默认为浏览器提供的异步操作。

Or is there some way to make one's own function truly asynchronous without leveraging very specific functions of the environment...

或者有没有办法让自己的功能真正异步,而不利用环境的非常具体的功能......

Until recently, no. Up through the 5th edition specification, JavaScript the language was basically silent on the entire concept of threads and asynchronicity; it was only when you got into environments that it came up. The only way to make something asynchronous was to use a host-provided function, such as nextTick (or any of the various operations that completes asynchronously) on NodeJS or setTimeout on browsers.

直到最近,没有。通过第5版规范,JavaScript语言基本上对线程和异步性的整个概念保持沉默;只有当你进入环境时它才出现。使异步生成的唯一方法是使用主机提供的函数,例如在NodeJS上的nextTick(或异步完成的任何各种操作)或浏览器上的setTimeout。

In the ECMAScript 6th edition specification in June 2015, they introduced promises into the language. The callbacks hooked up to an ES6 promise via then and such are always invoked asynchronously (even if the promise is already settled when the callback is attached), and so JavaScript has asynchronicity at a language level now. So if you implement your function so that it returns a promise rather than accepting a callback, you'll know that the then callbacks hooked up to it will be triggered asynchronously.

在2015年6月的ECMAScript第6版规范中,他们将承诺引入该语言。通过那时回调连接到ES6承诺,并且总是异步调用(即使在附加回调时承诺已经解决),因此JavaScript现在在语言级别具有异步性。因此,如果您实现您的函数以便它返回一个promise而不是接受一个回调,那么您将知道连接到它的then回调将异步触发。

#2


8  

To create your own asynchronous functions you have to make use of other asynchronous functions which may be provided by the interpreter.

要创建自己的异步函数,必须使用解释器可能提供的其他异步函数。

This code for example defines a function "addKeyHandler" which is asynchronous. But that only works because document.onKey is called asynchronously by the JS engine. The JavaScript engine is able to provide asynchronous functionality because the operating system provides such functionality which is then used by JS. The OS in turn can only provide async functionality because the hardware provides it (called hardware interrupts).

例如,该代码定义了一个异步的函数“addKeyHandler”。但这只能起作用,因为JS引擎异步调用document.onKey。 JavaScript引擎能够提供异步功能,因为操作系统提供了这样的功能,然后由JS使用。操作系统反过来只能提供异步功能,因为硬件提供它(称为硬件中断)。

However if the OS and hardware didn't provide any async functions it would still be possible to write a JS interpreter. But it would have to use an infinite loop and check in each iteration if any events occured and then invoke the appropriate callbacks. That would mean the CPU would always be under full load.

但是,如果操作系统和硬件没有提供任何异步功能,那么仍然可以编写JS解释器。但它必须使用无限循环并检查每次迭代是否发生任何事件,然后调用适当的回调。这意味着CPU总是处于满负荷状态。

var keyCallbacks = [];

var addKeyHandler = function(f) {
  keyCallbacks.push(f);
};

document.onkeypress = function(e) {
  keyCallbacks.forEach(function(f) {
      f(e);
  });
};

addKeyHandler(function(e) {
    console.log(String.fromCharCode(e.charCode));
});

#3


6  

Callbacks that you call yourself are regular function calls, which are always synchronous.

您自己调用的回调是常规函数调用,它们始终是同步的。

Certain native APIs (eg, AJAX, geolocation, Node.js disk or network APIs) are asynchronous and will execute their callbacks later in the event loop.

某些本机API(例如,AJAX,地理定位,Node.js磁盘或网络API)是异步的,稍后将在事件循环中执行其回调。

If you call a callback synchronously from within an async callback, it will end up being async too.

如果从异步回调中同步调用回调,它也将最终异步。

#4


0  

Simply taking a callback doesn't make a function asynchronous. There are many examples of functions that take a function argument but are not asynchronous, for example, Array's forEach.

简单地进行回调不会使函数异步。有许多函数的例子采用函数参数但不是异步的,例如,Array的forEach。

For a function to be asynchronous it needs to perform an asynchronous operation. Ways of introducing asynchronicity can be

对于异步函数,它需要执行异步操作。引入异步性的方法可以是

  • timer functions setTimeout, setInterval
  • timer函数setTimeout,setInterval
  • special functions nextTick, setImmediate
  • 特殊功能nextTick,setImmediate
  • performing I/O (listening to network, querying a database, reading or writing from a resource)
  • 执行I / O(侦听网络,查询数据库,从资源读取或写入)
  • subscribing to an event
  • 订阅活动

According to article "Does taking a callback make a function asynchronous?"

根据文章“采取回调是否使函数异步?”