Javascript: добавить таймаут после каждого запроса в функции карты Promise.all - PullRequest
0 голосов
/ 18 мая 2018

Для следующей функции мне нужно добавить таймаут после каждого запроса GET в массиве ajaxUrls.Все XHR GET-запросы находятся в массиве ajaxUrls.

function getAllSearchResultProfiles(searchAjaxUrl) {
  var ajaxUrls = [];
  for (var i = 0; i < numResults; i += resultsPerPage) {
    ajaxUrls.push(searchAjaxUrl + "&start=" + i);
  }
  return Promise.all(ajaxUrls.map(getSearchResultsForOnePage))
    .then(function(responses) {
      return responses.map(function(response) {
        if (response.meta.total === 0) {
          return [];
        }
        return response.result.searchResults.map(function(searchResult) {
          return (searchResult);
        });
      });
    })
    .then(function(searchProfiles) {
      return [].concat.apply([], searchProfiles);
    })
    .catch(function(responses) {
      console.error('error ', responses);
    });
}

function getSearchResultsForOnePage(url) {
  return fetch(url, {
      credentials: 'include'
    })
    .then(function(response) {
      return response.json();
    });
}

. Я хочу определенный таймаут или задержку после каждого GET-запроса.Я сталкиваюсь с трудностями в том, где именно добавить время ожидания.

Ответы [ 3 ]

0 голосов
/ 18 мая 2018

Если вы хотите делать запросы последовательно, вы не должны использовать Promise.all, который инициализирует все параллельно - лучше использовать reduce, await с разрешением предыдущей итерации и await обещание-тайм-аут.Например:

async function getAllSearchResultProfiles(searchAjaxUrl) {
  const ajaxUrls = [];
  for (let i = 0; i < numResults; i += resultsPerPage) {
    ajaxUrls.push(searchAjaxUrl + "&start=" + i);
  }
  const responses = await ajaxUrls.reduce(async (lastPromise, url) => {
    const accum = await lastPromise;
    await new Promise(resolve => setTimeout(resolve, 1000));
    const response = await getSearchResultsForOnePage(url);
    return [...accum, response];
  }, Promise.resolve([]));

  // do stuff with responses
  const searchProfiles = responses.map(response => (
    response.meta.total === 0
    ? []
    : response.result.searchResults
  ));
  return [].concat(...searchProfiles);
}

Обратите внимание, что только асинхронные операции должны передаваться из одной .then в другую;синхронный код не должен быть связан с .then, просто используйте переменные и выведите код как обычно.

0 голосов
/ 18 мая 2018

Я считаю, что простой цикл for в функции async является наиболее читабельным, даже если не обязательно наиболее лаконичным для подобных вещей.Пока функция является функцией async, вы также можете создать красивую функцию pause(), которая делает код очень простым для понимания, когда вы вернетесь позже.

Я немного упростил, но этодолжен дать вам хорошую идею:

function pause(time) {
  // handy pause function to await
  return new Promise(resolve => setTimeout(resolve, time))
}
async function getAllSearchResultProfiles(searchAjaxUrl) {
  var ajaxUrls = [];
  for (var i = 0; i < 5; i++) {
    ajaxUrls.push(searchAjaxUrl + "&start=" + i);
  }
  let responses = []
  for (url of ajaxUrls) {
    // just loop though and await

    console.log("sending request")
    let response = await getSearchResultsForOnePage(url)

    console.log("recieved: ", response)
    responses.push(response)
    await pause(1000) // wait one second

  }
  //responses.map() and other manilpulations etc...
  return responses
}

function getSearchResultsForOnePage(url) {
  //fake fetch
  return Promise.resolve(url)
}
getAllSearchResultProfiles("Test")
  .then(console.log)
0 голосов
/ 18 мая 2018

Если вы хотите добавить задержку в каждом запросе, тогда добавьте setTimout() в вашу функцию, которая выбирает данные из API

function getSearchResultsForOnePage(url) {
  return new Promise((resolve, reject) => {
   fetch(url, {
      credentials: 'include'
   })
   .then(response => reresponse.json())
   .then(data => {
     let timeout = 1000;
     setTimeout(() => resolve(data), timeout);
  });
 }
...