开始
最近在利用node的express的web框架来开发MVC模式的网站后台。其中在Model层为了便于操作mysql进而返回数据,我封装了mysql的连接池操作到一个单独文件,又由于node的完全异步的实现思路,导致习惯了python编写的我直接编写起来很蛋疼,所以我利用promise方法将其封装成了同步。
这是原(部分)代码
1 |
|
async/await 同时使用
async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。这样就可以以同步的写法得到select结果。在本实例中我手动实现了promise对象返回,随后在使用query的Model层中在此方法前添加await并封装成async的方法
1 |
|
随后,理论上同步写法已完成,但是实际上存在严重的错误。
错误出现
这是追加的mysql模块提示的掉线连接代码并报错的代码
1 |
|
在随后的测试中,我发现程序存在十分特别的情况,当请求本express框架十次之后,会报错
(node:13944) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added to [Pool]. Use emitter.setMaxListeners() to increase limit (Use "node --trace-warnings ..." to show where the warning was created)
大概意思是监听器过多,会导致内存泄漏。
这错误提示只会在node app.js时复现,nodemon则不会
解决思路
我猜测可能是由于返回的pool对象被重复使用导致的问题,随后查到node在新版中已经使用缓存方式加载模块,理论上并不会存在着这种情况。
由于query返回了一个封装成promise的方法,而pool的createPool已经写好了,返回的promise方法里只有pool.getConnection()。所以有可能在实现过程中执行query方式后通过getConnection()方法连接到连接池,但是由于createPool()方法写在了外部导致node不会在query方法被调用后返回该方法缓存,而是重新执行了query()方法。最终重复生成监听器。
将pool = mysqlcreatePool({})方法写进return new promise中
1 |
|
解决问题。经过测试写在query方法中也行。
另
在不写pool.relase()的情况下当createpool写在query方法外会导致达到连接池上限后无法连接。这是我最初的问题
将createpool写在promise中,无relase也能正常执行,可能是由于执行完成后自动执行了断开数据库连接的方法。这样好像会导致pool完全用不到?也不知道pool的连接方法有没有加强性能
实际上我也不清楚这个问题是如何解决的233。