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

jac*_*son 33 javascript asynchronous synchronous node.js

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

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

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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

T.J*_*der 42

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

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

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

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

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

是什么让jQuery的AJAX异步?

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

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

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

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


Spi*_*Pig 9

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

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

但是,如果操作系统和硬件没有提供任何异步功能,那么仍然可以编写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));
});
Run Code Online (Sandbox Code Playgroud)


SLa*_*aks 7

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

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

如果从异步回调中同步调用回调,它最终也会异步.