Javascript 堆叠可选承诺的正确方法
使用Promissions从DB收集所有数据的正确或最佳方法是什么,但使用nativeJavascript 堆叠可选承诺的正确方法,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,使用Promissions从DB收集所有数据的正确或最佳方法是什么,但使用nativeNodePromissions 目标只是展示所选内容: const allPromises = []; const selected = { sectionA: true, sectionB: false, sectionCIds: [ 1, 2, 4 ], }; if (selected.sectionA) { allPromises.push(getSectionADataFromDbPr
Node
Promissions
目标只是展示所选内容:
const allPromises = [];
const selected = {
sectionA: true,
sectionB: false,
sectionCIds: [ 1, 2, 4 ],
};
if (selected.sectionA) {
allPromises.push(getSectionADataFromDbPromise());
}
if (selected.sectionB) {
allPromises.push(getSectionBDataFromDbPromise());
}
if (selected.sectionCIds.length > 0) {
allPromises.push(selected.sectionCIds
.map(getSectionCDataFromDbPromise)
);
}
Promise.all(allPromises)
.then((allResults) => {
if (selected.sectionA) {
dataA = allResults[0];
}
if (selected.sectionA) {
dataB = allResults[1];
}
if (selected.sectionC) {
dataC = allResults[2]; // <-- this will not work if B is not selected
}
// ... same logic to build report: return Promise.all()...
});
const allPromises=[];
所选常数={
A部分:是的,
B部分:错误,
第CIDS节:[1,2,4],
};
如果(已选定。第A节){
push(getSectionADataFromDbPromise());
}
如果(已选择。第B节){
push(getSectionBDataFromDbPromise());
}
如果(所选的.sectionCIds.length>0){
allPromises.push(选定的.sectionCIds
.map(getSectionCDataFromDbPromise)
);
}
承诺,全部(全部承诺)
。然后((所有结果)=>{
如果(已选定。第A节){
dataA=所有结果[0];
}
如果(已选定。第A节){
数据=所有结果[1];
}
如果(已选定。第C节){
dataC=allResults[2];//不幸的是,与Q等库不同,标准的Promise
没有公开接受promises对象的all的变体
但是,我们可以使用新的ES2015和ES2017Object
实用方法来帮助我们保持代码的可读性
const allPromises = {};
const selected = {
sectionA: true,
sectionB: false,
sectionCIds: [1, 2, 4],
};
if (selected.sectionA) {
allPromises.sectionA = getSectionADataFromDbPromise();
}
if (selected.sectionB) {
allPromises.sectionB = getSectionBDataFromDbPromise();
}
if (selected.sectionBIds.length > 0) {
allPromises.sectionC = Promise.all(selected.sectionBIds
.map(getSectionCDataFromDbPromise)
);
}
现在我们可以写作了
Promise.all(Object.entries(allPromises).map(([key, promise]) =>
promise.then(value => ({[key]: value}))
))
.then(allResults => {
const results = Object.assign({}, ...allResults);
const data = {
a: results.sectionA,
b: results.sectionB,
c: results.sectionB && results.sectionC
};
// ... same logic to build report: return Promise.all()...
});
您对此有何看法?它更大、更重、更难,但都是自动化的和完全进化的。要处理新参数吗?参数现在有数据了吗?仅更改地图
我创建了一个映射,其中包含了使用循环所需的所有内容。数据的状态(激活或未激活)、获取数据所需调用的函数等等
const mapSelected = {
sectionA: {
state: true,
func: getSectionADataFromDbPromise,
},
sectionB: {
state: false,
func: getSectionBDataFromDbPromise,
},
sectionC: {
state: true,
func: getSectionCDataFromDbPromise,
data: [
1,
2,
4,
],
},
};
然后我们使用我们创建的映射创建promise数组。处理有数据和无数据的情况
const promises = Object.values(mapSelected).reduce((tmp, {
state,
func,
data,
}) => {
if (!state) return tmp;
if (data && data.length) {
return [
...tmp,
...data.map(x => func.call(this, x)),
];
}
return [
...tmp,
func.call(this),
];
});
然后我们根据承诺返回为地图上的每个键创建数组。你可以更改我显示数据的方式,我不知道你真正想要的是什么
Promise.all(promises)
.then((allResults) => {
let i = 0;
const [
dataA,
dataB,
dataC,
] = Object.values(mapSelected).reduce((tmp, {
state,
data,
}, xi) => {
if (!state) return tmp;
if (data && data.length) {
data.forEach(x => (tmp[xi].push(allPromises[i++])));
return tmp;
}
tmp[xi].push(allPromises[i++]);
return tmp;
}, Object.values(mapSelected).map(() => []));
});
@编辑
我只是做了一段代码,运行它
函数a(){
返回1;
}
常量映射选择={
A节:{
国家:是的,
func:a,
},
B节:{
国家:错,
func:a,
},
C节:{
国家:是的,
func:a,
数据:[
1.
2.
4.
],
},
};
常量所有承诺=[
0,
1.
2.
3.
4.
];
设i=0;
常数[
达塔,
数据库,
数据中心,
]=对象.值(mapSelected).reduce((tmp{
国家,,
数据,
},xi)=>{
如果(!state)返回tmp;
if(数据和数据长度){
data.forEach(x=>(tmp[xi].push(allPromises[i++]);
返回tmp;
}
tmp[xi].push(allPromises[i++]);
返回tmp;
},Object.values(mapSelected).map(()=>[]);
console.log(dataA);
控制台日志(dataB);
console.log(dataC);
不要有条件地对数组使用push
,而是始终将相同的值放在相同的索引中。即使该值为nothing-Promise。所有都会处理得很好
const selected = {
sectionA: true,
sectionB: false,
sectionCIds: [ 1, 2, 4 ],
};
Promise.all([
selected.sectionA ? getSectionADataFromDbPromise() : null,
selected.sectionB ? getSectionBDataFromDbPromise() : null,
Promise.all(selected.sectionCIds.map(getSectionCDataFromDbPromise))
]).then(([dataA, dataB, dataC]) => {
if (selected.sectionA) {
// use dataA
}
if (selected.sectionA) {
// use dataB
}
if (dataC.length) { // same as selected.selectionCIds.length
// use dataC
}
});
第三部分真的很难读,它抛出了“tmp不适用”.@VladimirVukanac我正在查看它,就像状态和循环部分一样!反应就像!我必须重构每个if-in函数的内部。无论如何,这不是问题。我还试图解决第三部分,并将其解耦,以便从多个位置使用。@VladimirVukanac我刚刚用伪Prom重新创建了第一部分ise数据,它运行没有问题。请确保你有相同的东西。请随意使用你有权知道的代码编辑你的帖子,以便我们查看并帮助你。我认为过滤器
不会起作用,因为它无法像那样访问键。但是过滤器根本不需要,只需执行e> 赋值({},…所有结果)
!为什么c:results.sectionB&&results.sectionC
?正如我在评论中所写的那样,您的解决方案将保留索引,因为如果未选择某个节,您将返回null。因此,反对push
的建议与此无关。@VladimirVukanac是的,保留索引是正确的Solution(不管你是怎样做的)。我强调的是,你不应该有条件地推送数组,而应该总是推送一个值(例如,在if
和else
中同时使用推送
)。当然,你可以完全避免推送
,只需将所有内容都放在数组文本中,这样更简洁(我也更可读)。非常简单