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