【问题标题】:How to execute AJAX calls in order in loop using Javascript Promise如何使用 Javascript Promise 循环执行 AJAX 调用
【发布时间】:2021-04-28 18:35:04
【问题描述】:

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

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

【问题讨论】:

  • 因为 $.ajax 返回一个(几乎)承诺,承诺链接将是一种方式

标签: javascript jquery ajax asynchronous promise


【解决方案1】:

由于 $.ajax 返回一个 Promise,你可以使用 Promise 链来实现你想要的

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,没有原生的 Promise

或者使用Array的reduce函数

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

如果你可以使用 ES2015+,那么原生 Promises,

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

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

【讨论】:

  • .reduce() (可以说)稍微修饰一下。
  • 这太好了,你能解释一下 JQuery 方式是如何知道何时移动到下一个调用的吗?
  • 这就是 promises 的工作原理……developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/… 比我解释得更好
  • @JaromandaX 它如何知道它在 AJAX 中成功而不是失败?我读了链接,但看不懂
  • jquery ajax 返回promise 成功时resolves 和rejects 失败...你知道resolve 和reject 对promise 意味着什么吗?
【解决方案2】:

如果您可以在项目中使用 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,它演示了这种方法。

【讨论】:

  • async await 与 $.when() 相比有什么优势?
  • @user8571142 $.when 是 jQuery 特有的方法,它与所有 javascript 世界都不相关。另外,我喜欢 Jaromanda X 的 reduce 解决方案,但 for + await 更具可读性。所有的魔法都隐藏在 async/await 实现下,这使得异步逻辑看起来像同步的。
【解决方案3】:

链式承诺应该可以工作:

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

用法:

ajaxPromises(['http://yoururl.com','http://yoururl.com'])
  .then(function (result) {
    // do something with result
  })
  .catch(function (error) {
    //  do something with error
  })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多