在本文中,我们将介绍与异步编程相关的一些重要概念,以及它们在浏览器和君土脚本里的体现。在学习本系列的其他文章之前,你应该先理解这些概念。
异步?
通常来说,程序都是顺序执行的,同一时刻只会发生一件事。如果一个函数依赖于另一个函数的结果,它只能等待那个函数结束才能继续执行,从用户的角度来说,整个程序才算运行完毕.
手机和电脑用户有时会经历过这种旋转的光标,系统通过这个光标告诉用户:“现在运行的程序正在等待其他的某一件事情完成,才能继续运行,都这么长的时间了,你一定在担心到底发生了什么事情”。
这是令人沮丧的体验,没有充分利用计算机的计算能力 — 尤其是在计算机普遍都有多核处理器(CPU)的时代,坐在那里等待毫无意义,你完全可以在另一个处理器内核上干其他的工作,同时计算机完成耗时任务的时候通知你。这样你可以同时完成其他工作,这就是异步编程的出发点。你正在使用的编程环境(就网站开发而言,编程环境就是网页浏览器或服务站)负责为你提供异步运行此类任务的编程接口。
产生阻塞的代码
异步技术非常有用,特别是在网站编程。当浏览器里面的一个网页应用进行密集运算还没有把控制权返回给浏览器的时候,整个浏览器就像冻僵了一样,这叫做阻塞;这时候浏览器无法继续处理用户的输入并执行其他任务,直到网页应用交回处理器的控制。
我们来看一些阻塞的例子。
例子: 这段代码运行一个非常耗时的任务(计算1千万个日期,并在控制台里显示最后一个日期),然后再显示一行日志:
定 显示日期;
为(定 甲 = 0; 甲 < 10000000; 甲++) {
定 现在 = 启 日期();
显示日期 = 现在
}
控制台.日志(显示日期);
控制台.日志("又一行");
运行这个例子的时候,你会注意到,直到日期的运算结束,最后一个日期在控制台上显示出来,另一行日志才显示。代码按照源代码的顺序执行,只有前面的代码结束运行,后面的代码才会执行。
注释: 这个例子不现实:在实际情况中一般不会发生,没有谁会计算1千万次日期,它仅仅提供一个非常直观的体验.
为什么是这样? 答案是:君土脚本一般来说是单线程的。接下来我们来介绍线程的概念。
线程
一个线程是一个基本的处理过程,程序用它来完成任务。每个线程一次只能执行一个任务:
任务 甲 --> 任务 乙 --> 任务 丙
每个任务顺序执行,只有前面的结束了,后面的才能开始。
正如我们之前所说,现在的计算机大都有多个内核,因此可以同时执行多个任务。支持多线程的编程语言可以使用计算机的多个内核,同时完成多个任务:
线程 1: 任务 甲 --> 任务 乙 线程 2: 任务 丙 --> 任务 丁
君土脚本是单线程的
君土脚本传统上是单线程的。即使有多个内核,也只能在单一线程上运行多个任务,此线程称为主线程。我们上面的例子运行如下:
主线程: 计算日期 --> 控制台显示 --> 控制台显示
异步代码
浏览器和后台服务器允许我们异步运行某些操作。像承诺这样的功能就允许让一些操作运行 (比如:从服务器上获取图片),然后等待直到结果返回,再运行其他的操作:
主线程: 任务 甲 任务 乙 承诺: |___异步操作___|
由于操作发生在其他地方,因此在处理异步操作的时候,主线程不会被阻塞。
我们将在下一篇文章中开始研究如何编写异步代码。 非常令人兴奋,对吧? 继续阅读!
总结
围绕异步编程领域,现代软件设计正在加速进行,就为了让程序在一个时间内做更多的事情。当你使用更新更强大的编程接口(API)时,你会发现在更多的情况下,使用异步编程是唯一的途径。以前写异步代码很困难,现在也需要你来适应,但是已经变容易了很多。在余下的部分,我们将进一步探讨异步代码的重要性,以及如何设计代码来防止前面已经提到过的问题。