NodeJS 在异步函数(asyncawait)中调用栈打印不全的问题

JavaScript031

NodeJS 在异步函数(asyncawait)中调用栈打印不全的问题,第1张

我在 index.ts 中调用 time-helper.ts 中的 waitForFn(),出错的调用栈是这样的:

这个调用栈有啥问题呢?只显示出了 time-helper 模块的文件信息,完全不显示调用者的信息,这样一来,完全不知道是谁调用了这个 waitForFn() 函数。你从错误信息里都不知道是哪个函数出错了。

出现这种情况,原因在这里:「链接」

解决办法在这里:「链接」

简单总结下 ,就是:

在异步函数返回之前,系统会清空当前调用线,然后把异步函数中的调用栈写进去。

解决办法 :只要把tsconfig.json文件中的compilerOptions.target改成es2018或以上的版本即可。

改完后效果:

可见整个调用栈都非常清晰。

Python

Ruby

也有这样的框架,但因为在实际使用中会不可避免地用到含有同步代码的库,因此没能成长起来,而在

Node.js

之前,JavaScript

的服务器端编程几乎是空白,所以

Node.js

才得以建立起了一个所有

IO

均为异步的代码库。

大部分

Web

应用的瓶颈都在

IO,

即读写磁盘,读写网络,读写数据库。使用怎样的策略等待这段时间,就成了改善性能的关键点。

PHP

的策略:多进程运行,直接原地等待

IO

完成。缺点:多个进程会消耗多份内存,进程间难以共享数据。

C/C++

通常的策略:多线程运行,程序自己维护锁的状态。缺点:开发成本高,容易出错,不易调试。

Python(Tornado):

多个请求在单个进程中轮流执行,遇到

IO

时切换到另一个请求。缺点:对于单个请求而言,依然没有最高效地利用时间。

何谓「最高效地利用时间」?比如现在有两个不相关的数据库查询,在

PHP

中通常会先执行一个,执行完成后再执行第二个(总时间是

a

+

b).

显然这不是最高效的,应该同时执行两个查询,时间是

max(a,

b).

Python

和其他支持多线程的语言的问题就在于,在语言层面,程序员很难告诉虚拟机,应当将两个操作同时执行,即使有办法,也相当麻烦,大多数人懒得去用(也不值得去用)。而因为

Node.js

丧心病狂地强制所有

IO

异步执行,Node.js

的程序员也可以说是轻车熟路,配合一些改善代码可读性库(promise,

async),

可以很轻松地让不相干的操作并行执行。

上面讲了异步

IO

的实现,那么异步

IO

的优势究竟体现在哪里呢。实际上异步

IO

并不能神奇地减轻服务器的压力,该加服务器还是一样要加服务器,只不过异步

IO

会减少单个请求的时间,去掉单个请求中那些无意义的等待时间。所以单位时间内处理的请求没有变化,但每个请求的处理时间却减少了。从这个角度,服务器也节约了一些资源——即维持每个请求的连接消耗的内存。