所有的javascript回调都是异步的吗?如果没有,我怎么知道哪些是
Are all javascript callbacks asynchronous? If not, how do I know which are?
我很好奇是否所有的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);
但是,例如,我知道jQuery的AJAX函数是真正的异步(不考虑现在可用的承诺(。是什么让jQuery的AJAX异步?它是否像涉及 XHR 请求那么简单,并且在浏览器中,所有 XHR 请求都是异步的?
我对nodejs环境有同样的问题。节点中的某些内容只有在涉及文件 i/o、process.nextTick、setTimeout 或 setInterval 之类的内容时才可以是异步的吗?为什么当我使用 mongodb/mongoose 进行数据库调用之类的事情时,它是异步的吗?幕后发生了什么,使它如此?
异步"情况"是否由环境预先确定?或者有没有办法在不利用环境中非常具体的功能(例如xhr,node中的file io,process.nexttick等(的情况下使自己的函数真正异步?
我很好奇是否所有的javascript回调都是异步的
不。例如,Array#sort
使用的回调不是异步的,String#replace
使用的回调也不是异步的。
了解回调是否异步的唯一方法是从其文档中获取。通常,涉及外部资源请求(例如 ajax 调用(的那些是异步的,而其他的可能是也可能不是。
但是,例如,我知道jQuery的AJAX函数是真正的异步...
不一定,因为目前 jQuery 仍然有 async
标志,您可以false
设置该标志以强制同步请求。(这不是一个好主意,他们会删除它,但你可以。 jQuery将标志传递给提供同步/异步行为的底层浏览器对象。
是什么让jQuery的AJAX异步?
jQuery的ajax调用使用XMLHttpRequest
对象(或在某些情况下使用script
元素(,该对象默认为浏览器提供的异步操作。
或者有没有办法使自己的功能真正异步,而不利用环境中非常具体的功能......
直到最近,还没有。直到第 5 版规范,JavaScript 语言基本上对线程和异步性的整个概念保持沉默;只有当你进入环境时,它才会出现。使某些内容异步的唯一方法是使用主机提供的函数,例如在 NodeJS 上nextTick
(或异步完成的各种操作中的任何一种(或在浏览器上setTimeout
。
在 2015 年 6 月的 ECMAScript 第 6 版规范中,他们将 promise 引入该语言。通过 then
挂接到 ES6 承诺的回调总是异步调用的(即使在附加回调时承诺已经解决(,因此 JavaScript 现在在语言级别具有异步性。因此,如果你实现你的函数,让它返回一个承诺而不是接受回调,你就会知道挂接到它的then
回调将被异步触发。
您自己调用的回调是常规函数调用,它们始终是同步的。
某些本机 API(例如,AJAX、地理位置、节点.js磁盘或网络 API(是异步的,稍后将在事件循环中执行其回调。
如果从异步回调中同步调用回调,则它最终也将是异步的。
要创建自己的异步函数,您必须使用解释器可能提供的其他异步函数。
例如,此代码定义了一个异步函数"addKeyHandler"。但这只有效,因为 document.onKey 是由 JS 引擎异步调用的。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));
});
简单地进行回调不会使函数异步。有许多函数接受函数参数但不是异步的函数的例子,例如,
Array
的forEach
。要使函数异步,它需要执行异步操作。引入异步性的方法可以是
- 定时器功能
setTimeout
、setInterval
- 特殊功能
nextTick
,setImmediate
- 执行 I/O(侦听网络、查询数据库、从资源读取或写入(
- 订阅活动
根据文章"进行回调会使函数异步吗?
寻找一个简单的答案:
除非你正在处理承诺,否则 JS 回调只有在它们依赖于 JS 外部的 API(例如浏览器提供的(时才是异步的。
setTimeout
、fetch
等都是异步的,因为它们依赖于外部 API。(例如,setTimeout
是windowOrGlobalWorker
Web API 的一部分,而fetch
本身就是一个 Web API。
如果回调不依赖于外部 API,则它是同步的。
承诺是JS中唯一的本机异步功能。
了解所有这些问题的好方法是至少阅读 MDN 入门中关于异步的前几篇文章:https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous
- AngularJS-我怎么知道何时解决了对父控制器的承诺
- 我怎么知道用户什么时候点击了类似Facebook的按钮
- 我怎么知道Jqgrid已经准备好了
- 我怎么知道 .ajax 是使用 Get 还是 POST
- 我怎么知道是整数一位或两位数
- 我怎么知道日期是否是星期六
- 摩卡“每个钩子之前”红色消息.我怎么知道具体出了什么问题
- 我怎么知道什么元素是通过jquery拖进来的
- 我怎么知道,我的Javascript执行
- 我怎么知道括号指的是什么
- 我怎么知道本机 JS 对象没有被篡改
- 所有的javascript回调都是异步的吗?如果没有,我怎么知道哪些是
- 我怎么知道一个模型是否在Backbone.js中没有被改变?
- 我怎么知道如果一个DOM对象是在窗口使用JavaScript
- 我怎么知道如果一个给定的字符串是十六进制,rgb, rgba或使用javascript/jquery的hsl颜色
- HTML4和HTML5 -如果没有导航,我怎么知道是否有一个“返回”状态
- 如果我有一个元素的x角和y角的位置,我怎么知道元素A是否在元素B中
- 我怎么知道如果我可以推迟我的网页上的JS脚本
- 使用yepno,我怎么知道如果css资源被成功加载
- 我怎么知道如果我点击一个网页上的png透明或不透明的部分