如何使用catch,最后与when.map
我想使用when.map
函数来处理一些数据。 数据处理后,我需要做一些清理(例如释放当前使用的数据库连接回连接池)。
我的方法使用catch
的问题, finally
是finally
被调用,当第一个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
,并将触发cache
, finally
处理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.map
replacewhen.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