【问题标题】:Using array.map, promises, and setTimeout to update an array使用 array.map、promises 和 setTimeout 更新数组
【发布时间】:2019-02-01 11:21:56
【问题描述】:

我希望遍历用户数组(仅设置 id 属性),每两秒使用每个 id 调用一个端点,并将响应中的关联用户名存储到更新数组。

例如更新 [{ id: 1 }] [{ id: 1, name: "Leanne Graham" }]

这是我的代码:

const axios = require('axios');

const users = [{ id: 1 }, { id: 2 }, { id: 3 }];

function addNameToUser(user) {
  return new Promise((resolve) => {
    axios.get(`https://jsonplaceholder.typicode.com/users/${user.id}`)
      .then(response => {
        user.name = response.data.name
        resolve(user);
      });
  })
}

const requests = users.map((user, index) => {
  setTimeout(() => {
    return addNameToUser(user);
  }, index * 2000);
});

Promise.all(requests).then((updatedArr) => {
  console.log(updatedArr);
});

没有setTimeout,一切都很好,但重要的是我只每两秒发送一个请求。所以对于三个用户,我想在六秒左右后从我的Promise.all 日志中看到结果。

值得注意:这不是我正在处理的实际问题,而是我能想出的最简单的例子来帮助突出这个问题。

【问题讨论】:

标签: javascript arrays node.js promise settimeout


【解决方案1】:

据我了解,您问题的核心是如何将您的处理间隔 2 秒,对吧?

const users = [{ id: 1 }, { id: 2 }, { id: 3 }];

/* throttledProcess is a function that does your processing spaced by the given interval millisecond */
const throttledProcess = (items, interval) => {  
  if (items.length == 0) { // stop when there's no more items to process
    console.log('ALL DONE')
    return
  }  
  console.log('PROCESSING', items[0], Date()) // this is where your http call/update/etc takes place
  setTimeout(() => throttledProcess(items.slice(1), interval), // wrap in an arrow function to defer evaluation
    interval)
}

throttledProcess(users, 2000) // run process. shows output every 2 seconds

运行此代码,每 2 秒,它将注销正在处理的用户。

希望这会有所帮助。 干杯,

【讨论】:

    【解决方案2】:

    您需要从地图的回调中返回一个 Promise。由于此承诺将由setTimeout() 解决,因此我们将使用Promise constructor

    已解决的超时承诺应返回 Axios 承诺,该承诺将在解决时返回结果。

    注意:由于 Axios 返回一个 Promise,我们不需要用另一个 Promise 构造函数包装它。见What is the explicit promise construction antipattern and how do I avoid it?问答。

    const users = [{ id: 1 }, { id: 2 }, { id: 3 }];
    
    const addNameToUser = (user) => 
      axios.get(`https://jsonplaceholder.typicode.com/users/${user.id}`)
      .then(({ data }) => ({
        ...user,
        name: data.name
      }));
    
    const requests = users.map((user, index) =>
      new Promise(resolve => 
        setTimeout(() => resolve(addNameToUser(user)), index * 2000)
      ));
    
    Promise.all(requests).then((updatedArr) => {
      console.log(updatedArr);
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>

    【讨论】:

      猜你喜欢
      • 2020-08-19
      • 2020-03-15
      • 1970-01-01
      • 2019-08-26
      • 2012-05-30
      • 1970-01-01
      • 1970-01-01
      • 2018-04-01
      • 2016-12-06
      相关资源
      最近更新 更多