Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 堆叠可选承诺的正确方法_Javascript_Node.js_Promise_Es6 Promise - Fatal编程技术网

Javascript 堆叠可选承诺的正确方法

Javascript 堆叠可选承诺的正确方法,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

使用Promissions从DB收集所有数据的正确或最佳方法是什么,但使用native
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和ES2017
Object
实用方法来帮助我们保持代码的可读性

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
中同时使用
推送
)。当然,你可以完全避免
推送
,只需将所有内容都放在数组文本中,这样更简洁(我也更可读)。非常简单