如何使用catch,最后与when.map

我想使用when.map函数来处理一些数据。 数据处理后,我需要做一些清理(例如释放当前使用的数据库连接回连接池)。

我的方法使用catch的问题, finallyfinally被调用,当第一个reject发生,而其他映射仍在进行中。

那么我怎么才能等到所有的映射承诺都完成了,这样才有可能做一个保存清理。

  require('when/monitor/console'); var when = require('when'); function testMapper(value) { console.log('testMapper called with: '+value); return when.promise(function(resolve, reject) { setTimeout(function() { console.log('reject: '+value); reject(new Error('error: '+value)); },100*value); }); } when.map([1,2,3,4],testMapper) .then(function() { console.log('finished') }) .catch(function(e) { console.log(e); }) .finally(function() { console.log('finally') }); 

产量

  testMapper called with: 1 testMapper called with: 2 testMapper called with: 3 testMapper called with: 4 reject: 1 [Error: error: 1] finally reject: 2 [promises] Unhandled rejections: 1 Error: error: 2 at null._onTimeout (index.js:9:14) reject: 3 [promises] Unhandled rejections: 2 Error: error: 2 at null._onTimeout (index.js:9:14) Error: error: 3 at null._onTimeout (index.js:9:14) reject: 4 [promises] Unhandled rejections: 3 Error: error: 2 at null._onTimeout (index.js:9:14) Error: error: 3 at null._onTimeout (index.js:9:14) Error: error: 4 at null._onTimeout (index.js:9:14) 

Environmentinformation:

  • whenjs:v3.1.0
  • 节点:v0.10.26

你最好的select就是跟着when.settle ,当他们解决的时候回复所有的承诺,而不是在他们完成的时候返回所有的promise,所以你可以手动检查哪一个做得好,哪一个没有。

 var arrayOfPromises = array.map(testMapper); when.settle(arrayOfPromises).then(function(descriptors){ descriptors.forEach(function(d){ if(d.state === "rejected"){ // do cleanup for that promise, you can access its rejection reason here // and do any cleanup you want } else{ // successful results accessed here console.log("Successful!", d.value); } }) }); 

注意:

这其实不是一个小问题。 当我说不是一个小问题,我的意思是这是一个很难正确解决的巨大问题。 这里有多个隐含的行为和边缘案例。

考虑阅读这个有点冗长的讨论 。 如果你愿意考虑 – 蓝鸟有一个实验性的promise-using分支,允许指定处置器,这将让你做到这一点相当容易。

你将能够做到:

 using(pool.getConnectionAsync().disposer("close"), function(connection) { return connection.queryAsync("SELECT * FROM TABLE"); }).then(function(rows) { console.log(rows); }); 

或者在多资源的情况下:

 var a = Promise.cast(externalPromiseApi.getResource1()).disposer("close"); var b = Promise.cast(externalPromiseApi.getResource2()).disposer("close"); using(a, b, function(resource1, resource2) { // once the promise returned here is resolved, we have a deterministic guarantee that // all the resources used here have been closed. }) 

根据Benjamin Gruenbaum的回答,我创build了一个替代的内部使用解决的when.map ,并将触发cachefinally处理map所有promise。

  var settle = {}; var arrayMap = Array.prototype.map; settle.map = function(array, f) { var arrayOfPromises = arrayMap.call(array,function(x) { return when.resolve(x).then(f); }); return when.settle(arrayOfPromises) .then(function(descriptors) { var result = []; descriptors.forEach(function(descriptor) { if( descriptor.state === 'rejected') { throw descriptor.reason; } result.push(descriptor.value); }); return result; }); }; 

当我现在用我的原始代码中的settle.mapreplacewhen.map ,那么输出/执行顺序是我所需要的:

  testMapper called with: 1 testMapper called with: 2 testMapper called with: 3 testMapper called with: 4 reject: 1 reject: 2 reject: 3 reject: 4 [Error: error: 1] finally