【问题标题】:How can I use .then() on an Array?`如何在数组上使用 .then()?
【发布时间】:2018-01-06 00:43:28
【问题描述】:

我在 Express/Sequelize 应用中做了很多基于 Promise 的操作。为了控制数据流,我想尽可能地遵循promise模型。

这是我目前正在做的事情:

 AreaList.forEach( area => {
      distances.push({
        target: tgt,
        source: area,
        distance: areaController.calcDist(tgt, area),
        country: areaController.determineCountry(area)
      }).then(() => { //this is where I would like to have the .then() function, but get the error.
      distances.sort((a1, a2) =>{
        return a1.distance - a2.distance;
      }).filter(area => area.country === country)
      .forEach(area => {
       Insider.findAll({
        where: {
         areaCode: area.source,
         country: area.country,
         language: language,
         gender: gender
        }
      }).then( insider => {
        returnUsers.push(insiders);
      }).then(_ => {
        returnUsers = returnUsers.splice(0,10);
        res.status(200).send(returnUsers);
      });
    });
  });
});

如何为数组提供.then(),或模拟.then()

【问题讨论】:

  • 数组的push函数返回数组中新的元素个数,没有then函数用于数字。由于push 函数不能异步工作,所以这里不需要使用promise,只需将push 新项添加到数组中,然后继续sort
  • 你不需要then函数,只需结束命令,写一个温柔的;并返回下一行:推送函数是同步的
  • 我假设AreaList 是一个项目数组。您想处理一个接一个的项目(串行),同时处理(并行)还是并行,但每个周期的最大 x 数量(例如每秒最多 5 个)或最大 x 活动量(例如不超过 5 个活动连接) ?您的代码中有哪些异步函数? areacontroller 函数是同步的还是异步的?我假设Insider.findAll 是异步的,那是唯一的异步函数吗?
  • 忘记了。如果一个失败了,你想要那些成功的还是失败的?
  • AreaList 应该串行处理。 areaController 是这段代码的来源模块,是的,findAll() 函数是异步的,这就是为什么我对这种异步和同步代码的混合感到困惑。

标签: javascript arrays promise


【解决方案1】:

您遇到的问题是将同步代码与异步代码混合在一起。在上面的代码 sn-p 中,您有各种同步代码。 AreaList.forEachdistances.pushdistances.sort都是同步操作。

在我看来,您正在尝试做的是处理一些代码,同时将其推入数组,这可能是异步的,也可能不是异步的 (areaController.calcDist(tgt, area))。

假设areaController.calcDist(tgt, area) 是一个同步操作,我会重写这样的内容:

let distances = AreaList.map(area => {
  return {
    target: tgt,
    source: area,
    distance: areaController.calcDist(tgt, area),
    country: areaController.determineCountry(area)
  };
})
.sort((a1, a2) =>{
    return a1.distance - a2.distance;
})
.filter(area => area.country === country);

let findUsers = distances.map(area => {
   return Insider.findAll({
    where: {
     areaCode: area.source,
     country: area.country,
     language: language,
     gender: gender
    }
   });
  });

Promise.all(findUsers).then(users => {
  let returnUsers = users.splice(0, 10);
  res.status(200).send(returnUsers);
})
.catch(err => {
  //handle errors
});

【讨论】:

  • 天哪!看起来很漂亮!我要重新实现这个!
【解决方案2】:

then() 是 javascript promise resolve 提供的一个函数。如果您想在遍历 AreaList 中的每个项目时执行一系列操作,您应该这样做:

pushDistances(distance) {
    return new Promise((resolve) => {
        distance.push(distance);
        resolve();
    });

使用 resolve() 函数,您既可以在没有任何内容的情况下直接 resolve() 它,也可以附加您想要解析的内容:例如您刚刚推送的距离或带有新推送距离的更新距离数组。

resolve(distances) or resolve(distance);

然后在您的 .then() 中,根据您解决的问题,您可以得到距离或距离。像这样:

pushDistances().then((distance or distances) => {
  within this function you have access to distance or distances: based on what you resolved with. 
});

然后你可以链接一堆返回承诺的函数

pushDistances().then(() => anotherFunctionThatReturnsPromise()).then(() => {})

这是对 Promise 工作原理的概述。你应该多看看 Javascript Promises 了解如何链接承诺。

【讨论】:

    猜你喜欢
    • 2021-05-13
    • 1970-01-01
    • 2018-02-03
    • 2011-02-03
    • 1970-01-01
    • 2018-04-04
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多