如何 return 从 .then 承诺

How to return promise from .then

我希望能够链接 promise 以使代码同步。我的问题是,根据第一个 $http 请求的结果,我可能想要发送另一个请求。 如果我选择不发送另一个 $http 请求,我不需要我的第二个 then() 来做任何事情。但是因为我的第二个 then() 不知道这一切而且它仍然挂在那里所以我想我需要先 return 然后是一些虚假的虚拟承诺。但我也想在第二个 then() 中识别这种情况。我从第一个案例中想出了 returning $q.when('some value') 。这是代码:

$http.get(url, params)
    .then(function(res) {
        res = res.data;
        if (res.status == 'ok' && res.rows.length > 0) {
            $scope.roomTypes = res.rows;
            return $q.when({ isDummy: true }); //in this case I don't need to send another request
        } else if (res.rows.length === 0 && $scope.request.roomType) {
            return $http.get(url2, params2); //make second request and return then`able promise
        }
    }, function(res) {
        throw 'Error';
    })
    .then(function(res) {
        res = res.data;
        if (res.status == 'ok') {
            var roomType = {
                room_type: res.roomType.id,
                description: res.roomType.description
            };
            $scope.roomTypes.push(roomType);
        } else if (res.isDummy) {
            //ok that's our dummy promise 
        } else {
            //format of response unexpected it means something went wrong
            throw "error";
        }
    }, funcrtion(res) {
        throw "some Error";
    })
    .catch(function(res) {...})
    .finally(function() {...});

问题是我想查看解决 promise 的值 ({isDummy: true}),但我该怎么做?我在 res 参数中得到 undefined

res 将在此处未定义

      .then(function(res) {
        res = res.data;
        ...

因为 {isDummy: true} 对象上没有 data 属性。

尝试 return 除 promise 或 deferred 之外的任何对象 :) 并且其值将传递给 then。像这样:

return { isDummy: true };

示例代码:https://jsfiddle.net/817pwvus/

来自 jQuery when documentation:

If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately. The doneCallbacks are passed the original argument.

如果你想要代码同步,你总是可以在第一个写一个长代码块。

如果你想链式承诺 (Post:url1)->(Post:url2) 等等:

1.Thereturn没用。 2. 假设您有 2 个要链接的 $http 承诺,例如,它们都来自名为 $users 的服务,并且它们分别称为 GetUserAge 和 GetRelevantBars,并且第二个查询基于第一个查询的结果。

angular
 .module("moduleA")
 .controller("exmapleCtrl",exampleCtrl);

exampleCtrl.$injector=["$users"];

function exampleCtrl($users){
 var vm=this;

 vm.query = $users.GetUserAge().then( /*OnSuccess*/ GetUserAgeCB)

 //Callback of the GetUserAgeCB;
 function GetUserAgeCB(result){
  $users.GetRelevantBars().then( /*OnSuccess*/ GetRelevantBarsCB);
  /*continuation of CallBack code*/
 }


 //Callback of the GetRelevantBarsCB;
 function GetRelevantBarsCB(result){
  /*CallBack code*/
 }

}

希望这是可以理解的..

我认为这里的基本问题是将 promise 与 promise 处理程序混淆了。成功处理程序应该 return 一个值,而不是另一个承诺。当您在承诺成功处理程序中时,您是 'wrapped' 承诺机制,该机制将您 returned 值并将其传递给下一个处理程序。这意味着您的第二个承诺看不到初始响应,而是第一个承诺 returned.

除非您按原样传递该值,否则它会被处理。

例如 这一切都归结为你的行

return $q.when({isDummy: true});

应该是

return {isDummy: true};

问题出在另一种情况下,您希望继续进行下一个查询。我可能会执行以下操作之一: 1. 从第一个承诺处理开始(使用第一个处理程序的相关逻辑)。 2.传递url2和params - return({url: url2, params: params}) 在第二个promise中处理

注意 promise chanins 甚至可以在中间中断,如果任何处理程序拒绝,将不会调用以下成功处理程序,here is a simple example(确保打开您的 devtools 控制台以查看日志)。

与其返回一个虚拟值并明确忽略它,不如嵌套第二个处理程序并将其仅附加到需要它的承诺:

$http.get(url, params)
.then(function(res) {
    var data = res.data;
    if (data.status == 'ok' && data.rows.length > 0) {
        $scope.roomTypes = data.rows;
        return; // do nothing
    } else if (res.rows.length === 0 && $scope.request.roomType) {
        return $http.get(url2, params2)
        .then(function(res) {
            var data = res.data;
            if (data.status == 'ok')
                $scope.roomTypes.push({
                    room_type: data.roomType.id,
                    description: data.roomType.description
                });
            else
                throw "error";  //format of response unexpected it means something went wrong
        });
    }
})
.catch(function(res) {…})
.finally(function() {…});