admin管理员组

文章数量:1277399

I am looking to iterate through an array of users (with only the id property set), call an endpoint every two seconds with each id, and store the associated user's name from the response into an updated array.

e.g. update [{ id: 1 }] to [{ id: 1, name: "Leanne Graham" }]

Here is my code:

const axios = require('axios');

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

function addNameToUser(user) {
  return new Promise((resolve) => {
    axios.get(`/${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);
});

Everything works great without the setTimeout, but it's important that I only send a request every two seconds. So for three users, I would like to see the result from my Promise.all log after six seconds or so.

Worth noting: This is not the actual problem I am working on, but the easiest example I could e up with to help highlight the issue.

I am looking to iterate through an array of users (with only the id property set), call an endpoint every two seconds with each id, and store the associated user's name from the response into an updated array.

e.g. update [{ id: 1 }] to [{ id: 1, name: "Leanne Graham" }]

Here is my code:

const axios = require('axios');

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

function addNameToUser(user) {
  return new Promise((resolve) => {
    axios.get(`https://jsonplaceholder.typicode./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);
});

Everything works great without the setTimeout, but it's important that I only send a request every two seconds. So for three users, I would like to see the result from my Promise.all log after six seconds or so.

Worth noting: This is not the actual problem I am working on, but the easiest example I could e up with to help highlight the issue.

Share Improve this question edited Aug 26, 2018 at 22:10 jrnxf asked Aug 26, 2018 at 21:56 jrnxfjrnxf 97411 silver badges25 bronze badges 2
  • 1 stackoverflow./questions/23803743/… – Benjamin Gruenbaum Commented Aug 26, 2018 at 21:59
  • Your mean is requests user1 and wait 2 seconds, requests user1 and wait 2 seconds, ... Or request user1 ended and wait 2 seconds, ... – hong4rc Commented Aug 27, 2018 at 11:46
Add a ment  | 

2 Answers 2

Reset to default 7

As I understand, the core of your question is how to space your processing by 2 seconds apart, right?

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

Run this code and every 2 secs, it will log out which user is being processed.

Hope this helps. Cheers,

You need to return a Promise from the map's callback. Since this promise will be resolved by the setTimeout(), we'll use the Promise constructor.

The resolved timeout promise should return the Axios promise, which will return the result when resolved.

Note: since Axios returns a Promise, we don't need to wrap it with another Promise constructor. See What is the explicit promise construction antipattern and how do I avoid it? question and answers.

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

const addNameToUser = (user) => 
  axios.get(`https://jsonplaceholder.typicode./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./ajax/libs/axios/0.18.0/axios.min.js"></script>

本文标签: javascriptUsing arraymappromisesand setTimeout to update an arrayStack Overflow