如何同步链式的jQuery承诺



我正在将3个AJAX请求链接到一个安息的端点:

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

我已经使用.then()建立了一系列承诺。但是,请求不是在预期的订单(1,2,3)中发生的,而是从OPTIONS请求开始的(2,1)。

为什么它们不会以预期的顺序发生?

如何确保正确的顺序顺序?

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链序列中正确执行。

请记住,每当您以parens作为参数之后通过func(),它都会立即执行该功能并将其返回值作为参数传递。由于上述原因,这不是您想要的.then()

如果您要控制传递给getData()的内容,则可以确保从putData()返回正确的东西,因为这将传递给getData()东西:

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

最新更新