使用array.map,promise和setTimeout更新数组

时间:2018-08-26 21:56:33

标签: javascript arrays node.js promise settimeout

我希望遍历一系列用户(仅设置了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日志中的结果。

值得一提的是:这不是我正在解决的实际问题,但是我想出的最简单的示例可以用来突出问题。

2 个答案:

答案 0 :(得分:2)

据我了解,您问题的核心是如何将处理间隔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秒将注销正在处理的用户。

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

答案 1 :(得分:0)

您需要从地图的回调中返回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>