Использование array.map, обещаний и setTimeout для обновления массива - PullRequest
0 голосов
/ 27 августа 2018

Я хочу перебрать массив пользователей (только с установленным свойством 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 голосов
/ 10 октября 2018

Как я понимаю, суть вашего вопроса заключается в том, как распределить обработку на 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 секунды он будет выходить из системы, какой пользователь обрабатывается.

Надеюсь, это поможет.Cheers,

0 голосов
/ 27 августа 2018

Вам необходимо вернуть Обещание из обратного вызова карты.Поскольку это обещание будет разрешено setTimeout(), мы будем использовать конструктор Promise .

Разрешение с разрешенным тайм-аутом должно возвращать обещание Axios, которое будет возвращать результат после разрешения.

Примечание: поскольку Axios возвращает Promise, нам не нужно оборачивать его другим конструктором Promise.См. Что такое явное обещание построения antipattern и как мне его избежать? вопрос и ответы.

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>
...