【问题标题】:Javascript: Add timeout after every request in Promise.all Map functionJavascript:在 Promise.all Map 函数中的每个请求后添加超时
【发布时间】:2018-05-18 03:37:22
【问题描述】:

对于以下函数,我必须在数组ajaxUrls在每个 GET 请求后添加超时。所有 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 请求后有一定的超时或延迟。我在确切地添加超时的地方遇到了困难。

【问题讨论】:

  • 您的意思是要串行发出请求,每个请求之间有一个超时,而不是并行?
  • @CertainPerformance 没错。
  • I have to add a timeout after every GET request - 为什么需要这样做? GET 请求有速率限制吗?

标签: javascript asynchronous get promise httprequest


【解决方案1】:

如果您想以串行方式发出请求,则不应使用 Promise.all,它会并行初始化所有内容 - 最好使用 reduceawaits 是上一次迭代的分辨率 awaits 承诺超时。例如:

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 链接,只需使用变量并照常写出代码即可。

【讨论】:

  • 在做responses.map之前你会如何积累回复?
  • 这就是reduce 所完成的——它在继续之前awaits 所有响应。
  • 您能否详细说明return[...accum, response]。这到底是做什么的?
  • ... 是扩展语法——解释器将...arrayLike 替换为arrayLike[0], arrayLike[1], arrayLike[2] 等。它基本上是concat 的更好版本。 [...accum, response] 等价于accum.concat(response)
  • 当我这样做时,我得到Uncaught (in promise) TypeError: accum is not iterableUncaught (in promise) TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
【解决方案2】:

我发现async 函数中的简单for 循环是最易读的,即使对于这样的事情不一定是最简洁的。只要该函数是一个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)

【讨论】:

    【解决方案3】:

    如果您想在每个请求中添加延迟,请在从 api 获取数据的函数中添加 setTimout()

    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);
      });
     }
    

    【讨论】:

    • 无济于事 - 请求仍将同时并行发送。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    • 2017-01-06
    相关资源
    最近更新 更多