如何依次发送Javascript / jQuery AJAX POST请求,使用Promises循环遍历请求数据数组?

时间:2018-04-20 11:01:13

标签: javascript jquery

我有很多文章, 通过文章标题的表格列表可视地指示, 我们必须执行特定的处理操作, 一个接一个地处理物品, 通过发送带有该文章ID的POST请求, 从表格列表中删除该行时,作为进度的可视指示符。

这是我原来使用的:

var article_ids = [1,2,...];
article_ids.each(function (value, index) {
  var id = value;
  jQuery.ajax({
    type: "POST",
    url: "index.php?process_article",
    data: {article_id: id},
    cache: false,
    async: false
  })
  .done(function(reponse) {
    console.log(response);
    jQuery('.article-id-' + id).css('display', 'none');
  });  
});

它在FireFox中工作正常,逐个处理项目,从表格列表中删除相应的行。

但是在谷歌浏览器中,所有这些似乎都是一次性处理的,而不是在另一个完成后发生的这些请求。

经过一些谷歌搜索,发现引用说使用Javascript Promises,我无法弄清楚如何使用这种情况。

然后,我将上面的内容更改为以下递归函数,它似乎在Chrome和Firefox上都能正常工作,请求一个接一个地发生:

var article_ids = [1,2,...];
function processIds(ids) {
  if (ids.length > 0) {
    id = ids.shift();     
    console.log("Processing ID: " + id);
    jQuery.ajax({
      type: "POST",
      url: "index.php?process_article",
      data: {article_id: id},
      cache: false
    })
    .done(function() {
      jQuery('.article-id-' + id).css('display', 'none');
      processIds(ids);
    });
  } else {
    alert("Successfully processed all articles.");
  }
}
processIds(article_ids);

疑惑:

  1. 这是一个很好的方法吗?
  2. 我们如何使用Javascript Promises实现相同的目标?

1 个答案:

答案 0 :(得分:0)

您建议的递归解决方案有效且有意义,IMO。在这种情况下,我通常使用Array.reduce

以下是一个例子:

function processIds(ids) {
  return ids.reduce((promise, nextId) => {
    return promise.then(() =>
      jQuery.ajax({
        type: "POST",
        url: "index.php?process_article",
        data: { article_id: nextId },
        cache: false,
      })
    );
  }, Promise.resolve());
}

请注意,在此示例中,promises中包含的返回值将被丢弃,并且仅保留最后一个值。如果需要,可以修改它以捕获和聚合所有返回值。

将其提取为可重用的内容也很容易。例如:

function forEachAsync(myArray, funcPromise) {
  return myArray.reduce((promise, nextValue) => {
    return promise.then(() => funcPromise(nextValue));
  }, Promise.resolve());
}

然后您可以使用新的forEachAsync函数,如下所示:

function processIds(ids) {
  return forEachAsync(ids, processArticle);
}

function processArticle(id) {
  return jQuery.ajax({
    type: "POST",
    url: "index.php?process_article",
    data: { article_id: nextId },
    cache: false,
  });
}

我相信最新版本的jQuery使用与JavaScript承诺兼容的承诺,但这是您应该检查并注意的事项。

我相信它们是在ES2015中引入的,而jQuery在v3.0中引入了兼容性。