如何同步链式jQuery承诺的顺序

时间:2016-12-11 08:12:15

标签: javascript jquery ajax promise

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

  1. 输入一些数据(返回{}和确定)
  2. 获取我刚才提供的数据
  3. 显示数据
  4. 我使用.then()建立了一系列承诺。但请求不会按预期顺序(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);
    }
    

1 个答案:

答案 0 :(得分:2)

在此代码中:

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

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

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

  2. 由于您立即执行getData(_id),因此无法在承诺链序列中正确执行。

  3. 请记住,每当你将func()后面的parens作为参数传递时,它会立即执行该函数并将其作为参数传递给它。由于上述原因,这不是您想要的.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);
    
    
    

相关问题