我需要在“并行”中执行异步函数,并以最佳结果继续执行程序.因此我写了这样的东西:
var p = []; for (var i = 0; i < 10; ++i) (function (index) { p.push(new Promise(function (resolve,reject) { setTimeout(function () { var success = Math.random() > 0.7; console.log("Resolving",index,"as",success ? "success" : "failure"); success && resolve(index); },Math.random() * 5000 + 200); })); })(i); Promise.race(p).then(function (res) { console.log("FOUND",res); }).catch(function (err) { console.log("ERROR",err); });
现在,我想知道在使用承诺时这是否是一个好习惯?是不是更频繁地解决或拒绝它们然后任何事情造成内存泄漏?他们每次最终都是GC吗?
解决方法
这将泄漏的唯一原因是因为p是全局的.设p = null;最后,或避免使用全局变量:
var console = { log: function(msg) { div.innerHTML += msg + "<br>"; }}; Promise.race(new Array(10).fill(0).map(function(entry,index) { return (function(index) { return new Promise(function(resolve) { setTimeout(function() { var success = Math.random() > 0.7; console.log((success? "R":"Not r") + "esolving "+ index +"."); success && resolve(index); },Math.random() * 5000 + 200); }); })(index); })).then(function (res) { console.log("FOUND: " + res); }).catch(function (err) { console.log("ERROR: " + err); });
<div id="div"></div>
只要p中的一个条目成功或者某个失败,以较早者为准,Promise.race就会释放p,并且setTimeout将在5.2秒后释放所有内容.然后JavaScript会愉快地收集承诺,无论它们是已被解决,被拒绝还是两者都没有.无害.
您唯一要避免的是垃圾收集被拒绝的承诺,因为这可能会触发浏览器警告,因为它表示Web编程错误.
当然,有3%的几率没有解决,在这种情况下,这将泄漏(直到你关闭标签).
这个好设计吗?
我认为这取决于功能的作用.如果它们是轻量级的,那么我没有看到问题.如果他们正在进行繁重的计算或有副作用,那么他们希望有一些API来取消操作,以帮助节省资源.