一次误用Promise后的体会

Promise的嵌套需要注意,一个返回Promise的Promise可能不会以你想象的方式运行。

最近有需求处理海量的并发任务(其实就是抓wikipedia的文章跳转关系),需要让所有的任务存在数据库中,而不是在内存里,否则像我的第一个版本一样,内存占用巨大,cpu爆表,还得关心断点续传(定时保存)。

写了一个叫做promiseWorker的工具函数,类似Promise.map,支持并发控制地处理一组Promise。不同之处在于,并不需要把Promise塞进去,而是传一个函数getWork,用来获取下一个要执行的Promise,如果没有下一个任务了,就返回null。

还是不难实现的,写了一个版本后,用之前发现一个问题,getWork里需要取数据库信息,这个也是异步的。所以我需要接受一个异步函数,返回一个Promise,这个Promise的结果是null或者是另一个Promise。

写了之后测,发现遇到诡异的情况,只取了一个任务,且执行完第一个任务后就停止了。

然后发现,await getWork() 得到的不是任务Promise,而是任务Promise的执行结果。它的实际意义,就和我想象中的 await await getWork() 一样。

网上搜了一下,发现了这个:https://www.v2ex.com/t/377941#r_4569121
很有趣。

根据网上的一些Promise实现,大概是,如果resolve的结果还是个Promise(有then方法),会改成在这个Promise的then里继续执行之后的操作。
然后误伤了我的这个实现需求。
不过这样一来,Promise套Promise就不用管需要几个await了,毕竟唯一的功能就是取回数据。

这大概是个比较难发现的深坑吧。记录之。

(ps:现在的解决方案是把return new Promise(...)改成return [new Promise(...)]。。。)

(附注:es6的解构赋值用在赋值已经存在的对象时,应该这么用:({a, b} = getAB()); 也就是要加一个括号在最外面。)