承诺改变for循环的全局variables

我正在尝试做一些JavaScript代码的不同风格的基准testing,这里是我有:

var Promise = require('bluebird'); var timer = function(name) { var start = new Date(); return { stop: function() { var end = new Date(); var time = end.getTime() - start.getTime(); console.log('Function:', name, 'finished in', time, 'ms'); } }; }; function regular (a, cb) { if (a % 2 === 0) return cb(null, a); return cb(a); } function promise (a) { return new Promise (function (resolve, reject) { if (a % 2 === 0) resolve(a); else reject(a); }); } var t = timer('regular'); var g = 0; for (var i = 1; i < 10001; i++) { regular(i, function(odd, even) { if (odd) g = g + (odd * 2); else g = g + (even * 3); }); } console.log('g:', g); // g: 125015000 t.stop(); var t2 = timer('promise'); var h = 0; for (var i = 1; i < 10001; i++) { promise(i).then(function(x) {h = h + (x*3);}).catch(function(x) {h = h + (x*2);}); } console.log('h:', h); // h: 0 t2.stop(); 

有趣的是,promise不会改变全局variables'h',我怎样才能使它返回与variables'g'相同的结果呢?

UPDATE

这是改变代码,试图得到最终结果,但承诺的非确定性给我们意想不到的结果。

 for (var i = 1; i < 10001; i++) { promise(i).then(function(x) { h = h + (x*3); if (x===10000) console.log('h:', h); }).catch(function(x) {h = h + (x*2);}); // h: 75015000 } 

目前我的代码给出了预期的输出更奇怪。

 for (var i = 1; i < 10001; i++) { promise(i).then(function(x) { h = h + (x*3); }).catch(function(x) { h = h + (x*2); if (x===9999) console.log('h:', h); // <- attention here }); // h: 125015000 } 

任何人都可以告诉我一个更好的代码,并解释上面的代码? (上面的代码显示当i为9999而不是10000时确定性的正确结果)

为了用promise来解决你的问题,你可以用reduce来包装所有的方法,然后听着所有的Promise完成,这是依次运行promise。

如果你喜欢,也可以使用Promise.all()并行运行所有的promise。

 function promise (a) { return new Promise (function (resolve, reject) { if (a % 2 === 0) resolve(a); else reject(a); }); }; var timer = function(name) { var start = new Date(); return { stop: function() { var end = new Date(); var time = end.getTime() - start.getTime(); console.log('Function:', name, 'finished in', time, 'ms'); } }; }; console.log('Right result', Array.from({length : 10000}, (el, i)=> (i + 1) % 2 === 0 ? (i+1)*3 : (i+1)*2).reduce((a,b)=> a + b)); var t2 = timer('promise'); var h = 0; Promise.all(Array.from({length : 10000}, (el, i)=> promise(i + 1).then(x =>{ h += x*3}).catch(x =>{ h += x*2 }) )) .then(()=>{ console.log('h:', h); t2.stop(); }); 

承诺总是asynchronous调用他们的.catch().catch()处理程序。 即使他们立即解决,他们也会让JS的当前线程完成执行,并会在“下一个打勾”上asynchronous调用.catch().catch()处理程序。

因此你的console.log('h:', h); 被执行之前的任何.then()处理程序已被调用。 如果将console.log()语句放入.catch() .then().catch()处理程序中,则会发现它们已被调用,但在console.log('h:', h); 叫做。

承诺被devise成一个asynchronous接口。 而且,非常重要的是asynchronous接口始终保持一致,所以即使promise同步parsing,他们仍然会在下一个tick上asynchronous调用它们的.catch().catch()处理程序,以使它们始终保持一致,开发​​人员使用他们不需要担心有时会得到asynchronous响应,有时会得到同步响应。 相反,他们总是asynchronous的回应。

正如我在我的评论中所说的,任何真实世界的编码情况都应该只对至less有时是asynchronous的操作使用承诺。 如果你的操作总是同步的(就像你上面的例子那样),那么它们就不应该使用promise,因为promise只是使得同步操作比使用直接的同步函数调用更加复杂。

另外,您的循环中的多个承诺操作不以任何给定的方式进行sorting或协调。 如果这些是真正的asynchronous操作,它们可以以任何顺序完成,并且您的hvariables的更新将具有不确定的顺序(这通常是一个问题,因此通常是不好的devise模式)。