如何从.then返回承诺

时间:2015-09-22 11:43:36

标签: javascript angularjs promise q deferred

我希望能够链接promises以使代码同步。我的问题是,根据第一个$ http请求的结果,我可能想要发送另一个或不。 如果我选择不发送另一个$ http请求,我不需要我的第二个then()做任何事情。但是因为我的第二个then()并不知道这一切,所以它仍然挂在那里,所以我想我需要先从一个假的假承诺回来。但我还想在第二个()中认识到这个案例。我想出了从第一个案例中返回$ 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() {...});

问题是我希望看到解决了承诺的价值({isDummy:true}),但我该怎么做?我在undefined参数中得到res

5 个答案:

答案 0 :(得分:1)

res将在此处未定义

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

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

答案 1 :(得分:1)

我认为这里的基本问题是将承诺与承诺处理程序混淆。成功处理程序应该返回一个值,而不是另一个promise。当你在一个promise成功处理程序中时,你会被promise机制“包装”,它会将你返回的值传递给下一个处理程序。这意味着你的第二个承诺没有看到初始响应,而是第一个承诺返回的内容。

除非按原样传递值,否则将继续处理该值。

例如 这一切都来自你的行

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

应该是

return {isDummy: true};

问题是另一种情况,您希望继续下一个查询。我可能会做以下其中一项: 1.从第一个承诺开始处理(使用第一个处理程序中的相关逻辑)。 2.传递url2和params - 返回({url:url2,params:params})并在第二个承诺中处理它们。

请注意,如果任何处理程序拒绝,则承诺通道甚至可以在中间中断,不会调用成功处理程序here is a simple example(确保打开devtools控制台以查看日志)。

答案 2 :(得分:0)

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

return { isDummy: true };

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

来自jQuery when documentation

  

如果将单个参数传递给jQuery.when()并且它不是Deferred或Promise,则它将被视为已解决的Deferred,并且将立即执行任何附加的doneCallbacks。 doneCallbacks传递原始参数。

答案 3 :(得分:0)

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

如果你想链接承诺(帖子:url1) - >(帖子:url2)等等:

1.回归无用。 2.假设你有2个$ http承诺你想要链接,例如,来自名为$ users的服务,他们调用GetUserAge和GetRelevantBars,第二个查询基于第一个查询#s; s结果

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*/
 }

}
希望这是可以理解的..

答案 4 :(得分:0)

您应该将第二个处理程序仅嵌套并附加到需要它的promise:而不是返回虚拟值并明确忽略该值:

$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() {…});