javascript - 如何同步链式 jQuery Promise 的顺序

标签 javascript jquery ajax promise

我将 3 个 ajax 请求链接到一个 RESTful 端点:

  1. PUT 一些数据(返回 {} 并确定)
  2. 获取我刚刚放的数据
  3. 显示数据

我已经使用 .then() 建立了一个 promise 链。但是请求并没有按照预期的顺序 (1,2,3) 发生,而是 (2,1) 并且以 OPTIONS 请求开始。

为什么它们没有按预期顺序发生?

如何确保顺序正确?

var _id = x;

function doReqs() {
  putData(_id, data)
    .then(getData(_id))
    .then(showData);
}

// returns empty object {}
function putData(id, data) {
  return $.ajax({
    method: 'PUT',
    url: http://xxx,
    contentType: 'application/json'
  });
}

// returns JSON {"data": {"xx": "xx}}
function getData(id) {
  return $.ajax({
    method: 'GET',
    url: http://xxx
  });
}

function showData(data) {
  console.log(data);
}

最佳答案

在这段代码中:

function doReqs() {
  putData(_id, data)
    .then(getData(_id))
    .then(showData);
}

.then(getData(_id)) 部分是错误的。这是错误的,原因有二。

  1. .then() 应该传递一个函数引用。当您传递 getData(_id) 时,您将立即执行该函数并将该函数的返回值(它是一个 jqXHR 对象)传递给 .then()。这不是您应该传递给 .then() 的内容。

  2. 因为您正在立即执行 getData(_id),所以它不会在 promise 链序列中正确执行。

请记住,任何时候您传递一个 func() 并将其后的括号作为参数传递时,它会立即执行该函数并将其返回值作为参数传递。由于上述原因,这不是您想要的 .then()

如果您试图控制传递给 getData() 的内容,那么您可以确保从 putData() 返回正确的内容,因为那是将传递给 getData() 的内容,或者您​​可以创建一个 stub 函数来传递正确的内容:

function doReqs() {
  putData(_id, data)
    .then(function() {
        return getData(_id);
    })
    .then(showData);
}

或者,你可以这样做:

function doReqs() {
  putData(_id, data)
    .then(getData.bind(null, _id))
    .then(showData);
}

或者,由于 putData() 的解析值将作为参数传递给 promise 链中的下一步(即 getData),您可以这样做:

function putData(id, data) {
  return $.ajax({
    method: 'PUT',
    url: http://xxx,
    contentType: 'application/json'
  }).then(function() {
    // make sure putData passes the id to the next step in the chain
    return id;
  });
}

function doReqs(id) {
  putData(id, data)
    .then(getData)
    .then(showData);
}

这是一个链式操作的工作示例:

function delay(t, val) {
   return new Promise(function(resolve) {
       setTimeout(resolve.bind(null, val), t);
   });
}

function first(arg) {
    console.log("running first..., arg = ", arg);
    return delay(500, 10);
}

function second(arg) {
    console.log("running second..., arg = ", arg);
    return delay(100, 100);
}

function third(arg) {
    console.log("running third..., arg = ", arg);
}

first(1).then(second).then(third);

关于javascript - 如何同步链式 jQuery Promise 的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41084184/

相关文章:

jquery - 如何在 jQuery UI 自动完成中设置至少两个字符?

ruby-on-rails - 使用 jquery 在 Rails 中渲染部分内容

jquery - 通过 AJAX(隐藏 Api)获取 google +1 页面共享

javascript - 从用户脚本中的匿名函数获取函数指针

javascript - 寻找一个通过向上和向下箭头键操作的日期小部件来增加日期

jquery - 如何通过 WWW::Mechanize::Firefox 调用 jQuery 或 Angular 函数?

javascript - 如何获取canvas中图像的Id

javascript - Jquery Ajax 调用未命中操作方法/返回整个 HTML 页面

javascript - Highcharts Highmap 世界 - 为大陆内的所有国家着色

javascript - 如何将方法导出到另一个模块