可以链接`.then()的返回响应的顺序与`.then()的顺序不同吗?

时间:2016-05-08 12:56:04

标签: javascript callback

在下面的示例中,服务器对doSomethingOne请求的响应是否可能在服务器响应doSomethingTwo的请求之前返回?

$scope.pace = $interval (
    function() {

        // code

    }, 1000, 10

).then(postResult)
    .then(doSomethingOne)
        .then(doSomethingTwo);

问题是因为,doSomethingOne将数据发布到数据库,然后doSomethingTwo正在查询数据库并返回一些数据,包括doSomethingOne应该发布的数据。

但对doSomethingTwo请求的回复并未包含doSomethingOne发布的最新数据(直到$scope.pace从头开始运行)

我对回调没有很强的理解(尽管有很多关于它们的阅读)所以任何建议都会非常感激。

简要说明

doSomthingOne执行$http.post()doSomethingTwo执行$http.get()。这里没有使用承诺。

1 个答案:

答案 0 :(得分:2)

<强>更新

从你的编辑:

  

doSomthingOne执行$ http.post()和doSomethingTwo执行$ http.get()。这里没有使用承诺。

好吧,$http.post returns a promise(有时在文档中称为“未来”),但如果您不使用它,那么在POST之前不会阻止doSomethingTwo被调用完成了。实际上,在POST完成之前(很久以前)可能会调用非常

你可以简单地通过返回promise $http.post返回来解决问题(或者如果你正在使用一个,则返回你对该promise的调用所创建的promise)。 E.g:

function doSomethingOne() {
    return $http.post(/*...args...*/);
}

function doSomethingOne() {
    return $http.post(/*...args...*/).then(/*...*/);
}

以下详情。

原始答案(仍然相关):

这取决于doSomethingOne做什么以及它返回什么。如果doSomethingOne启动异步进程但没有返回该进程的承诺,则可以在该进程完成之前调用doSomethingTwo。如果doSomethingOne同步工作(根据你所说的不太可能)或返回其异步工作的承诺,它将在调用doSomethingTwo之前完成,因为doSomethingTwo等待该承诺得到解决。

以下是doSomethingOne未返回异步工作承诺的示例,因此doSomethingTwo可能会在doSomethingOne的异步工作完成之前运行:

// Simulate an asynchronous DB call
function dbCall(data) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve("Result for " + data);
    }, Math.floor(Math.random() * 500));
  })
}
function start() {
  console.log("start called");
  return new Promise(resolve => {
    setTimeout(() => {
      console.log("start resolving");
      resolve();
    }, 0);
  })
}
function doSomethingOne() {
  // THIS IS PROBABLY WRONG
  console.log("doSomethingOne called");
  dbCall("one data").then(function(result) {
    console.log("doSometingOne's async is done");
  });
}
function doSomethingTwo() {
  console.log("doSomethingTwo called");
}
start().then(doSomethingOne).then(doSomethingTwo);

Live copy on Babel's REPL

这可能是错误的。相反,您希望doSomethingOne从异步工作中返回一个承诺;它可以通过在dbCall(...).then上返回其调用结果来实现:

// Simulate an asynchronous DB call
function dbCall(data) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve("Result for " + data);
    }, Math.floor(Math.random() * 500));
  })
}
function start() {
  console.log("start called");
  return new Promise(resolve => {
    setTimeout(() => {
      console.log("start resolving");
      resolve();
    }, 0);
  })
}
function doSomethingOne() {
  console.log("doSomethingOne called");
  return dbCall("one data").then(function(result) {
//^^^^^^^------------------------------------------- change is here
    console.log("doSometingOne's async is done");
  });
}
function doSomethingTwo() {
  console.log("doSomethingTwo called");
}
start().then(doSomethingOne).then(doSomethingTwo);

Live copy on Babel's REPL