首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >堆叠可选承诺的适当方法

堆叠可选承诺的适当方法
EN

Stack Overflow用户
提问于 2017-11-24 09:30:34
回答 3查看 103关注 0票数 5

用承诺从DB收集所有数据的正确或最好的方法是什么,但使用本机Node承诺。

其目标仅是介绍所选内容:

代码语言:javascript
运行
复制
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()...
  });

可能的解决办法:

  • 所选数据的跟踪索引(例如。C的索引为1)
  • 目标地图
  • 将其他{ allPromises.push(Promise.resolve(null)) }添加到每个if

也许有更简单的方法,或者这其中的一种会是正确的方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-24 10:28:44

不要对数组有条件地使用push,但是总是将相同的值放在相同的索引上。即使值是零,Promise.all也会处理得很好。

代码语言:javascript
运行
复制
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
  }
});
票数 2
EN

Stack Overflow用户

发布于 2017-11-24 09:59:16

你觉得这个怎么样?它更大,更重,更难,但它都是自动化的和完全进化的。想要处理一个新参数吗?参数现在有数据了吗?只需改变地图。

我创建了一个地图,它包含了使用循环所需的所有内容。数据的状态(激活与否)、调用以获取数据的函数等等。

代码语言:javascript
运行
复制
const mapSelected = {
  sectionA: {
    state: true,

    func: getSectionADataFromDbPromise,
  },

  sectionB: {
    state: false,

    func: getSectionBDataFromDbPromise,
  },

  sectionC: {
    state: true,

    func: getSectionCDataFromDbPromise,

    data: [
      1,
      2,
      4,
    ],
  },
};

然后,我们使用我们创建的映射创建承诺数组。用数据和没有数据来处理案件。

代码语言:javascript
运行
复制
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),
  ];
});

然后,我们根据映射中每个键的允诺返回来创建数组。你可以改变我呈现数据的方式,我不知道你真正想要的是什么。

代码语言:javascript
运行
复制
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(() => []));
  });

@编辑

我只是做了一个关于我所做的代码的片段,运行它

代码语言:javascript
运行
复制
function a() {
  return 1;
}

const mapSelected = {
  sectionA: {
    state: true,

    func: a,
  },

  sectionB: {
    state: false,

    func: a,
  },

  sectionC: {
    state: true,

    func: a,

    data: [
      1,
      2,
      4,
    ],
  },
};

const allPromises = [
  0,
  1,
  2,
  3,
  4,
];

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(() => []));

console.log(dataA);
console.log(dataB);
console.log(dataC);

票数 2
EN

Stack Overflow用户

发布于 2017-11-24 09:58:29

不幸的是,与Q这样的库不同的是,标准的Promise不公开all的变体,接受承诺的对象。

但是,我们可以使用新的ES2015和ES2017 Object实用程序方法来帮助我们保持代码的可读性。

代码语言:javascript
运行
复制
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)
  );
}

现在我们可以写

代码语言:javascript
运行
复制
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()...
  });
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47470147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档