javascript - 真正同步运行多次 fetch

标签 javascript jquery ajax fetch

我见过各种使 fetch 看起来同步的解决方案,例如使用await,但是它们必须包装在异步函数中,因此整个事情不是同步的。

我需要运行 fetch x 次,并按照开始的顺序完成每次迭代。如果我在 fetch 之后使用 .then ,它会在每个 fetch 实例之后运行,但结果(包括 .then 运行的函数的结果)将按响应顺序返回,因此列表按 a-z 顺序获取的 url 在输出时可能会部分随机返回,这是 Not Acceptable 。

我尝试使用带有 async: false 的 jquery ajax,虽然这使输出与输入保持顺序 - 当它成功运行时 - 它会在错误时无限期卡住,并且它的超时值在同步中不起作用模式。

我们似乎可以选择以潜在的随机顺序获取多个连续的 url,或者我们可以按顺序获取它们,使用同步模式下的 jquery ajax/XMLHTTPRequest,但当 URL 时会卡住浏览器超时,而我们设置的用于中止尝试检索 url 的超时值将被忽略。

下面是一个示例,它读取地址文本文件(每行一个),获取其市议会区,并将其附加到该行。它可以工作——除了输出行的顺序与输入的顺序不同,而且我还没有找到一种方法让它们在同步模式下,在 url 超时时不会无限期卡住。

<!DOCTYPE html>
<html><head><body>
  <h1>LAS - Find My District Widget</h1>
  <h2>Select a text file (.txt) with a list of addresses - each in a new line.  The Widget will return the corresponding districts.</h2>
  <input id="input-file" type="file">
  <hr><textarea id="output-box" cols="250"></textarea>
<script>
var baseUrl = "https://changedthistoprotectprivacy";
var input = document.getElementById('input-file');
var output = document.getElementById('output-box');

function writeSuccesOutput(geoclientResp) {
  var address = geoclientResp.input.replace(/(?:\r\n|\r|\n)/g,"");
  var cityCouncil = geoclientResp['results'][0].response.cityCouncilDistrict;
  var addressWithCcd = address + ' City Council District ' + cityCouncil + '\n';
  output.textContent += addressWithCcd;
}

function writeErrorOutput(error) {
  var address = geoclientResp.input.replace(/(?:\r\n|\r|\n)/g,"");
  var message = address + ' ERROR ' + error + '\n';
  output.textContent += message;
}

function geocode(address) {
  var querystring = encodeURI(address);
  var url = baseUrl + querystring;
  fetch(url).then(function(response) {
    response.json().then(writeSuccesOutput);
  }).catch(writeErrorOutput);
}

var reader = new FileReader();
reader.onloadend = function (event) {
  output.textContent = ''
  var addressList = event.target.result.split("\n");
  for (var i = 0; i < addressList.length; i++) {
    geocode(addressList[i]);
  }
}

input.onchange = function() {
  if (this.files && this.files[0]) {
    reader.readAsBinaryString(this.files[0]);
  }
}
</script>
</body>
</html>

最佳答案

您的实际要求是保持结果与输入的顺序相同,以便我们可以确定哪些坐标属于哪个地址。您可以使用 Promise.all() ,它会在给定所有 Promise 解析时进行解析,并以相同的顺序返回结果。

Promise.all()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

var reader = new FileReader();
reader.onloadend = function (event) {
  output.textContent = ''
  var addressList = event.target.result.split("\n");
  var prmises = addressList.map(address => geocode(address));
  Promise.all(promises).then(coordinates => {
    // here coordinates[0] is result for addressList[0] and so on
    
  });
}

// Here is a demo
const fakeApi = (address) => {
   const randrom = Math.random() * 1000 + 1000;
     return new Promise(resolve => {
     setTimeout(() => resolve(`${address}_${randrom}`), 10);
   });
};

const addresses = ['A', 'B', 'C', 'D', 'E', 'F'];

const promises = addresses.map(address => fakeApi(address));
console.log(addresses);
Promise.all(promises).then(results => {
  console.log(results);
});

关于javascript - 真正同步运行多次 fetch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50381326/

相关文章:

javascript - ajax 文件上传问题(Node.js、express、jQuery)

jquery - 奇怪的 jQuery AJAX 行为 : XML comes back as #document and not object

javascript - 如何在浏览器上无延迟地显示 "No Results"

javascript - jQuery 根据高度拆分内容

javascript - 使用 .css 移动对象后,重置所有可放置对象以允许可拖动对象

javascript - 如何解决 Google API 中的 CORS 问题?

javascript - 有没有一种方法可以使用类似于 contenteditable 的文本区域的用户提交值来更新 DOM?

javascript - 使用ajax更改不同页面范围内的内容

javascript - 为什么 IE 中 boolean true 有 toJSON 方法?

javascript - 按子项排序并检索其他子项值