异步:详解分析(一)

414 阅读2分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

程序中现在运行的部分和将来运行的部分之间的关系就是异步编程的核心

我们首先需要深入理解异步的概念及其在 JavaScript 中的运作模式。

1、分块的程序

可以把 JavaScript 程序写在单个 .js 文件中,但是这个程序几乎一定是由多个块构成的。这些块中只有一个是现在执行,其余的则会在将来执行。最常见的块单位是函数。

function now() { 
return 21; 
} 
function later() { 
answer = answer * 2; 
console.log( "Meaning of life:", answer ); 
} 
var answer = now(); 
setTimeout( later, 1000 ); // Meaning of life: 42

这个程序有两个块:现在执行的部分,以及将来执行的部分。

现在:

function now() { 
return 21; 
} 
function later() { .. } 
var answer = now(); 
setTimeout( later, 1000 );

将来:

answer = answer * 2; 
console.log( "Meaning of life:", answer );

现在这一块在程序运行之后就会立即执行。但是,setTimeout(..) 还设置了一个事件(定 时)在将来执行,所以函数 later() 的内容会在之后的某个时间(从现在起 1000 毫秒之 后)执行。

任何时候,只要把一段代码包装成一个函数,并指定它在响应某个事件(定时器、鼠标点 击、Ajax 响应等)时执行,你就是在代码中创建了一个将来执行的块,也由此在这个程序 中引入了异步机制。

异步控制台

并没有什么规范或一组需求指定 console.* 方法族如何工作——它们并不是 JavaScript 正式的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到 JavaScript 中的。

因此,不同的浏览器和 JavaScript 环境可以按照自己的意愿来实现,有时候这会引起混淆。 尤其要提出的是,在某些条件下,某些浏览器的 console.log(..) 并不会把传入的内容立 即输出。出现这种情况的主要原因是,在许多程序(不只是 JavaScript)中,I/O 是非常低 速的阻塞部分。所以,(从页面 /UI 的角度来说)浏览器在后台异步处理控制台 I/O 能够提 高性能,这时用户甚至可能根本意识不到其发生。

如果遇到这种少见的情况,最好的选择是在 JavaScript 调试器中使用断点, 而不要依赖控制台输出。次优的方案是把对象序列化到一个字符串中,以强 制执行一次“快照”,比如通过 JSON.stringify(..)。