如何使用Javascript Promise循环执行AJAX调用

时间:2017-11-10 02:46:35

标签: javascript jquery ajax asynchronous promise

我循环遍历一个地图,我想在每个地图值作为参数的情况下进行单独的AJAX调用,以获取一些数据并记录它。见下文。这是有效的,但我想按照地图的顺序进行AJAX调用。因为每次调用都是异步的,所以我应该使用promises来按顺序实现执行。但我是承诺的新手,并不知道如何在这里做到这一点。我在这里寻找其他地方但找不到任何东西。请帮忙。

map.forEach(function(url, key) {
   log(url);
});

function log(url) {
    $.ajax({
      url: url, 
      dataType: 'json',
      success: function (result) {
          console.log(result.value);
          console.log(result.name);
          console.log(result.action);
      }
  });
}

3 个答案:

答案 0 :(得分:4)

由于$ .ajax返回一个promise,你可以使用promise chaining来实现你想要的东西

var p = $.when();
map.forEach(function(url, key) {
    p = p.then(function() { 
        return log(url);
    });
});

function log(url) {
    return $.ajax({
        url: url, 
        dataType: 'json',
        success: function (result) {
            console.log(result.value);
            console.log(result.name);
            console.log(result.action);
        }
    });
}

注意:上面的代码只使用jQuery,没有本机承诺

或使用Array的reduce函数

map.reduce(function(p, url) {
    return p.then(function() { 
        return log(url);
    });
}, $.when());

如果你可以使用ES2015 +,那么有本机Promise,

map.reduce((p, url) => p.then(() => log(url)), Promise.resolve());

如果你愿意,你也可以这样做

function log(url) {
    return $.ajax({
        url: url, 
        dataType: 'json'
    });
}

map.reduce((p, url) => p.then(results => log(url).then(result => results.concat(result))), Promise.resolve([]))
.then(results => {
    results.forEach(result => {
        console.log(result.value);
        console.log(result.name);
        console.log(result.action);
    })
});

不同之处在于,一旦LAST请求完成,所有console.log都会发生(如果失败,则不会发生任何控制台日志)

答案 1 :(得分:1)

如果您可以在项目中使用async / await语法,那么没有什么比这更容易了:

async function log(url) { 
  return await 
    $.ajax({
      url: url,
      dataType: 'json',
    })
    .then(function(result) {
      console.log(result.value);
      console.log(result.name);
      console.log(result.action);
    });
}

async function run() {
  for (var i = 0; i < map.length; i++) {
    await log(map[i]);
  }
}

run();

您知道,我已将forEach更改为for循环。这对于await用法很重要,因为它提供了(而不是forEach和其他基于回调的循环)异步log调用的同步性。

UPD 以下是the Plunker,演示了这种方法。

答案 2 :(得分:0)

连锁承诺应该有效:

const decoder = new TextDecoder();
const encoder = new TextEncoder();

self.onmessage = e => {
  console.log(e.data);
  self.data = JSON.parse(decoder.decode(e.data));
  self.data.string = "imAStringToo";
  self.encoded = encoder.encode(JSON.stringify(self.data));
  console.log("data in Worker:", self.data);
  self.postMessage(self.encoded, [self.encoded.buffer]);
  delete self.data; 
  delete self.encoded;
  console.log("data deleted in Worker:", self.data, self.encoded);
}

用法:

function ajaxPromises(urls) {
  return Promise.all(urls.map(function(url) {
    return $.ajax({
      url: url, 
      dataType: 'json'
  })
})