likes
comments
collection
share

Nodejs如何使单线程的Javascript实现异步编程

作者站长头像
站长
· 阅读数 12

熟悉Javascript的同学一定听过一句话“Javascript是单线程的”,但神奇的是基于Javascript的Nodejs却十分适合在高并发场景下使用,Nodejs究竟是如何做的,本文带大家一起看下:

一、同步编程 VS 异步编程

1.什么是同步编程

看下官网的解释

Nodejs中文网

Nodejs如何使单线程的Javascript实现异步编程

MDN:

Nodejs如何使单线程的Javascript实现异步编程

从官网的描述当中,我们能大致将同步编程 与 代码顺序执行 划等号。

2.什么是异步编程

Nodejs如何使单线程的Javascript实现异步编程

异步,即不同步,也就是说代码可以不按照顺序执行。

为什么不希望代码顺序执行?

是因为当主程序中出现一些网络请求、文件I/O操作时,如果按照代码顺序执行,那么后续所有的代码将无法执行,只有干等着这些耗时操作完成。

Nodejs如何使单线程的Javascript实现异步编程

太不科学了,我反对。

因此,为了解决这个问题,异步编程就出现了。

二、异步编程的实现

1.回调函数

什么是回调函数:

Nodejs如何使单线程的Javascript实现异步编程

官方的解释还是比较抽象,不妨用一个小栗子来去理解:

Nodejs如何使单线程的Javascript实现异步编程

这里的A函数就是一个回调函数callback。callback原意为call then back(调用后返回),就是在主函数B中调用callback函数,callback函数执行完成后又立刻回到主函数,继续执行主函数中的代码。

问题:为什么不能在B函数中直接调用A函数?

因为通常在编写程序时,B函数都是语言内部或者其他开发者定义好的(如内置模块的方法),我们看不到也不能直接在B函数内部插入我们的代码。

Nodejs如何使单线程的Javascript实现异步编程

那我们如何介入B函数的执行呢,此时就可以通过回调函数以参数的方式传递给B函数,B函数在内部再调用这个回调函数,并将结果返回(最关键)

回调函数在异步编程中的应用

还是先看一个栗子

Nodejs如何使单线程的Javascript实现异步编程

在B函数中有一个异步逻辑setTimeout,2秒后返回一个对象。

思考一下,我们如何拿到这个对象?

答案是可以借助回调函数,在回调函数A中我们可以通过result参数的方式,拿到异步逻辑执行后的返回值。

(其实,其实回调函数A最主要的功能也就在于此,帮助我们在B函数外部拿到B函数内部异步操作的执行结果)

2.回调函数在异步编程中的应用

在分析回调函数在异步编程中的应用之前,我们还是先看一个小栗子:

问:如何使用Nodejs读取三个文件x,y,z,文件的读取顺序是x -> y -> z

哈哈,这太简单了,上代码:

Nodejs如何使单线程的Javascript实现异步编程

一顿操作,结果却发现

Nodejs如何使单线程的Javascript实现异步编程

哈哈,小意思,再执行一次让你们看下

Nodejs如何使单线程的Javascript实现异步编程

傻眼了,怎么会这样呢?我的顺序呢?

小结:fs.readFile是一个异步方法,也就是说实际上代码执行的顺序与代码编写的顺序不完全一致,那该怎么办?

换一种思路,既然回调函数可以是一个参数,并且能在回调函数中拿到主函数的执行结果,那能不能在回调函数中执行下一步操作,试一试。

Nodejs如何使单线程的Javascript实现异步编程

看起来很好,运行下看看

Nodejs如何使单线程的Javascript实现异步编程

再试一下

Nodejs如何使单线程的Javascript实现异步编程

完结撒花!

3.思考

虽然上面实现了异步编程,但是这样一个场景出现时:

产品经理:突然有一个需求,有300个文件需要按照顺序读取,麻烦用回调函数实现。

Nodejs如何使单线程的Javascript实现异步编程

我:好的,等等,多少,300层?

心理活动:我难道要嵌套300层,虽然可以实现,也太low了吧。可恶,得想想其他办法。

那如何优化,下一期我们将对异步调用的优化方案进行深入探讨。