Promise.map.map 并发时链失败但通过单元测试
Promise.map.map chain fails when there's concurrency but passes unit tests
我天真地以为我可以将 .map()
与 Promise.map()
链接起来,但看来我错了。我遇到了一个恼人的问题,即通过单元测试但在并发性很高时却未能通过真实世界的测试。我认为这使它成为 Stack Overflow 上值得注意的陷阱。
我更改了代码以使用通常的 .then()
模式,现在它似乎每次都能正常工作。
这里的问题是,与 JS 中的数组不同,我不能将 .map()
与 Promise.map()
链接起来,还是我做错了什么?我注意到我在工作版本中清理了一些 lint 问题,但这似乎并没有对行为产生影响。
下面是随机失败的代码(当并发性高时)和在低并发性单元测试中似乎一直有效的代码。请注意所有名为 return promises 的函数。
// this has concurrency issues. occasionally the function
// returns [{ key: undefined: val: correct }]
db.assocThreeFewCountsGet = function(manyid, atype) {
counts = [];
return db.assocThreeFewDistinctGet(manyid, atype)
.then(r => {
console.log('Distinct', r); // shows there are valid IDs
counts = r;
return Promise.map(r, fewid => {
return db.assocCount(manyid, fewid);
}).map((el, idx) => {
return { key: counts[idx], val: el };
});
});
};
// this appears to work correctly. key: and val: are correct
db.assocThreeFewCountsGet = function(manyid, atype) {
var ids;
return db.assocThreeFewDistinctGet(manyid, atype)
.then(r => {
ids = r;
console.log('Distinct IDs:', ids); // shows there are valid IDs
return Promise.map(ids, fewid => {
return db.assocCount(manyid, fewid);
});
}).then(counters => {
return counters.map((el, idx) => {
return { key: ids[idx], val: el };
});
});
};
counts = [];
的分配是可疑的,似乎 create a global variable。这会导致各种问题,包括 counts
引用异步方法并发执行中的最新数组。同样在您的工作代码中,出于相同的目的,您有 var ids
,这对每个调用都是本地的。
如果您在其他任何地方都不需要 counts
,请使用
修复您的代码
db.assocThreeFewCountsGet = function(manyid, atype) {
return db.assocThreeFewDistinctGet(manyid, atype)
.then(counts => {
console.log('Distinct', counts); // shows there are valid IDs
return Promise.map(counts, fewid => {
return db.assocCount(manyid, fewid);
}).map((el, idx) => {
return { key: counts[idx], val: el };
});
});
};
我天真地以为我可以将 .map()
与 Promise.map()
链接起来,但看来我错了。我遇到了一个恼人的问题,即通过单元测试但在并发性很高时却未能通过真实世界的测试。我认为这使它成为 Stack Overflow 上值得注意的陷阱。
我更改了代码以使用通常的 .then()
模式,现在它似乎每次都能正常工作。
这里的问题是,与 JS 中的数组不同,我不能将 .map()
与 Promise.map()
链接起来,还是我做错了什么?我注意到我在工作版本中清理了一些 lint 问题,但这似乎并没有对行为产生影响。
下面是随机失败的代码(当并发性高时)和在低并发性单元测试中似乎一直有效的代码。请注意所有名为 return promises 的函数。
// this has concurrency issues. occasionally the function
// returns [{ key: undefined: val: correct }]
db.assocThreeFewCountsGet = function(manyid, atype) {
counts = [];
return db.assocThreeFewDistinctGet(manyid, atype)
.then(r => {
console.log('Distinct', r); // shows there are valid IDs
counts = r;
return Promise.map(r, fewid => {
return db.assocCount(manyid, fewid);
}).map((el, idx) => {
return { key: counts[idx], val: el };
});
});
};
// this appears to work correctly. key: and val: are correct
db.assocThreeFewCountsGet = function(manyid, atype) {
var ids;
return db.assocThreeFewDistinctGet(manyid, atype)
.then(r => {
ids = r;
console.log('Distinct IDs:', ids); // shows there are valid IDs
return Promise.map(ids, fewid => {
return db.assocCount(manyid, fewid);
});
}).then(counters => {
return counters.map((el, idx) => {
return { key: ids[idx], val: el };
});
});
};
counts = [];
的分配是可疑的,似乎 create a global variable。这会导致各种问题,包括 counts
引用异步方法并发执行中的最新数组。同样在您的工作代码中,出于相同的目的,您有 var ids
,这对每个调用都是本地的。
如果您在其他任何地方都不需要 counts
,请使用
db.assocThreeFewCountsGet = function(manyid, atype) {
return db.assocThreeFewDistinctGet(manyid, atype)
.then(counts => {
console.log('Distinct', counts); // shows there are valid IDs
return Promise.map(counts, fewid => {
return db.assocCount(manyid, fewid);
}).map((el, idx) => {
return { key: counts[idx], val: el };
});
});
};