千家信息网

异步编程需要“意识”

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,虽然我们生活在一个异步的世界里,但对于多数编程初学者来说,异步还是很陌生。学习一门编程语言,通常都是从同步流程开始的,即顺序、分支和循环。而异步流程是什么呢--开始一个异步调用,然后……就没有然后了。
千家信息网最后更新 2026年11月01日异步编程需要“意识”

虽然我们生活在一个异步的世界里,但对于多数编程初学者来说,异步还是很陌生。学习一门编程语言,通常都是从同步流程开始的,即顺序、分支和循环。而异步流程是什么呢--开始一个异步调用,然后……就没有然后了。异步程序跑哪去了?

异步程序会以某种异步的形式在运行着,比如多线程、异步IO等,直到处理完成。那如果需要处理结果怎么办?给一个程序入口,让它处理完当前过程之后,把处理结果送到这个入口,然后执行另一段程序--俗称回调。回调一般使用 callback 这个名称,不过有时候我更喜欢使用 next,因为它代表着下一个处理步骤。

同步和异步的概念

现在我们接触到了一些概念,比如同步和异步,它们是什么?

这两个概念并不来源于编程语言,而是来源于低层指令,甚至更低层的--电路。它们是基于时序的两个概念,其中,"步"是指步调,所以同步表示相同的步调,而异步表示不同的步调。当然这两个概念提升到程序这个级别的时候,精确的意思与时钟无关,但所表示的意义仍然未变。

同步

举个生活中的例子来说明这个问题--排除买票。售票厅开了一个窗口,有一队人在排队依次买票。这个队伍中,前面一个人往前走了一步,后面的人才能往前走一步;前面的人在等待,后面的人就一定在等待。那么在理想的情况下,所有人可以同时向前迈步。OK,大家步伐一致,称为同步。

这里把售票窗口看作是处理器,每个人看作是等待执行的指令,买票这个动作就是在执行指令。它的特点是按步就班,如果一个人买票时间过长(指令执行时间过长),就会造成阻塞。

异步(多线程)

现在买票的人渐渐多起来,所以售票厅多开了几个窗口同时售票。每个单独的队伍仍然保持着同步,但不同的队伍之间,步伐不再一致,称为异步。A 队列售票很顺利,队伍在有序快速的前进,但 B 队列的某个顾客似乎在付费时遇到点麻烦,花了很长的时候,造成阻塞,但这对 A 队列并不产生影响。

这时候的售票厅可以看作是在以多线程的方式运行着异步程序。从这个例子可以看到异步的两个特点:其一,两个异步流程之间相互独立,它们相互不会阻塞(有个前提,不需要等待共享资源的情况下);其二,异步程序内部仍然是同步的。

异步(IO)

上面的例子比较符合多线程异步的情况。那 IO 异步又是什么样呢?

年底了,M 在准备年终汇报的资料,这可是个紧张的工作(CPU),要收集不少数据来写好些文案。为了其中一份文案,M 需要车间的生产数据,但跑一趟车间(IO)可需要花不少时间,所以他让 N 去车间收集数据,自己则继续写其它方案,同时等 N 把数据收集回来(启动异步程序)。半天以后,N 带回了数据(插入事件消息),M 继续完成手上的文案(完成当前事件循环),之后使用 N 带回来的数据开始撰写关于车间的报告(新的事件循环)……

IO 的处理速度比 CPU 慢得多,所以 IO 异步让 CPU 不必闲置着等待 IO 操作完成。当 IO 操作完成之后,CPU 会适地使用 IO 操作结果继续工作。

同步逻辑和异步逻辑

回到程序上来,我们以一个函数的处理过程来描述同步和异步的处理方式。

同步逻辑

那么,同步处理过程是:

接受输入 ⇒ 处理 ⇒ 产生输出

用一段伪代码来描述就是

注:本文中的伪代码比较接近 JavaScript 语法,而有时候为了说明类型,采用了 TypeScript 的类型申明语法。

function func(input) {    do something with input    return output}

这是标准的 IPO(Input-Process-Output) 处理。

异步逻辑

而异步呢,是:

接受输入 ⇒ 处理 ⇒ 启动下一步(如果有)

用伪代码来描述就是:

function asyncFunc(input, next) {    do something with input    if (next is a entry) {        next(output)    }}

这个过程称为 IPN(Input-Process-Next)。

注意到这里的 Next,下一步,只有一步。这一步,囊括了后续的若干步骤。所以这一步,只能是后续若干步骤封装出来一个模块入口,或者说函数。

因此,模块化思想在异步思维中是一个非常关键的思想。很多初学者写代码喜欢像记流水账一样一句句往下写,动不动就是成百上千行的函数,这就是一种缺乏模块化思想的表现。模块化思想需要训练,分析代码的相关性,提炼函数,提取对象,在具有一定经验之后还需要掌握模块细化的粒度平衡。这不是一朝一夕之功,不过我推荐看看"设计模式"和"重构"相关的书籍。

异步开发工具(SDK和语法层面的)

承诺(Promise)

再想想上面关于年终汇报的例子,M 请 N 去车间收集数据的时候,N 会说:"好的,我很快就把数据带回来",这是一种承诺。基于这个承诺,M 才能安排后面撰写关于车间的汇报材料。这个过程用伪代码来描述就是

function collectData(): Promise {    // N 去收集数据,产生了一个承诺    return new Promise(resolve => {        collect data from workshop        // 这个承诺最终会带来数据        resolve(data)    })}function writeWorkshopReport(data) {    write report with data}// 收集数据的承诺兑现之后,可将这个数据用于写报告collectData()    .then(data => writeWorkshopReport(data))

以 JavaScript 为代表的一些语言 SDK 中使用了 Promise。不过 C# 中是采用的 Task 和 Task<T>,相应的,使用了 Task.ContinueWith 和 Task<T>.ContinueWith 来代替 Promise.then。

异步逻辑同步化

上面提到了同步思维和异步思维在一个处理步骤中的区别。如果跳出一个处理步骤,从更大范围的处理流程来看,异步与同步其实也没多大区别,都是 输入-->处理-->产生输出-->将输出用于下一步骤,唯一要注意的是需要等待异步处理产生的输出,我们可以称之为异步等待。由于我们可以一边进行异步等待(async wait,简写 await),一边做别的事情,所以这个等待并不产生阻塞。但是,由于声明了这个等待,编译器/解释器会将后面的代码自动放在等待完成之后调用,这让异步代码写起来就像写同步代码一样。

上面的例子使用异步等待的伪代码会像这样

async function collectData(): Promise {    collect data from workshop    // 多数语言会把 async 函数的返回值封装成 Promise    return data}function writeWorkshopReport(data) {    write report with data}// await 只能用于声明为 async 的函数中async function main() {    data = await collectData()    writeWorkshopReport(data)}// 定义了异步 main 函数,一定要记得调用,不然它是不会执行的main()

像 C# 和 JavaScript 等语言都从语法层面规定了 await 必须用在声明为 async 的函数中,这就从编译/解释的层面限定了 await 的用途,只要使用了 await,那它所处的就一定是一个异步上下文。而 async 也要求编译器/解释器对其返回值进行一些自动处理,比如在 JavaScript 中,其返回值如果不是 Promise 对象,它会自动封装成一个 Promise 对象;而在 C# 中,它会自动封装成 Task 或 Task<T>(所以 async 方法的类型需要声明为 Task 或 Task<T>)。

注意,注意,注意

尽管语言服务在异步程序同步化方面已经做了很多工作,但是仍然避免不了一些人为错误,比如忘记写 await 关键字。在强类型语言中编译器会检查得严格一些,但如果是在 JavaScript 中,忘记写 await 意味着原本应该取得一个值的语句,会取到一个 Promise。解释器不会对此质疑,但程序运行的结果会不正确。

小结

总的来说,异步编程并不是特别困难的事情。使用 async/await 语言特性甚至可以用类似编写同步代码的方法来编写异步代码。但语法糖终究是糖,要想把异步编程掌握得更好,还是需要去了解和熟悉异步、回调、Promise、模块化、设计模式、重构等概念。

相关阅读

  • 从小小题目逐步走进 JavaScript 异步调用
  • 闲谈异步调用"扁平"化
  • 理解 JavaScript 的 async/await
  • C# 并行计算(Parallel 和 ParallelQuery)
处理 同步 代码 数据 程序 函数 语言 就是 概念 模块 步骤 车间 售票 编程 两个 例子 语法 过程 逻辑 思想 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 保险科技 互联网保险 互联网科技公司简介 互联网医疗科技 互联网女皇 腾讯科技 成都狮子座互联网科技 衡水科技产业互联网平台 海南科技产业互联网平台 汉立互联网科技有限公司联系电话 互联网教育科技公司vipkid 互联网科技实习生岗位职责 承德科技产业互联网发展 千方科技属于互联网企业吗 河南住房之家互联网科技 区块链结合互联网科技 黑云互联网科技有限公司 卡尔迅互联网科技有限公司 互联网科技包装股份有限公司上市 世界互联网科技成果奖 唐山双旺合互联网科技产业园 亚光科技低轨卫星互联网 奇酷互联网络科技 上海喔噻互联网科技 互联网科技ppt模板 多迪互联网科技有限公司 汽车互联网创新科技园 互联网经济与金融科技 长沙茂晟互联网科技有限公司 伊宁互联网科技做什么的 互联网公司属于科技吗 高科技和互联网的现代国家
0