简体   繁体   English

如何从.then返回承诺

[英]How to return promise from .then

I want to be able to chain promises in order to make code synchronous. 我希望能够链接诺言以使代码同步。 My problem is that depending on result of first $http request I could either be wanting to send another or not. 我的问题是,根据第一个$ http请求的结果,我可能要发送另一个请求,也可能不发送。 In case if I choose not to send another $http request I don't need my second then() to do anything. 如果我选择不发送另一个$ http请求,则不需要第二个then()做任何事情。 But since my second then() doesn't know about all this and it's hanging there anyway so I figured I need to return from first then some fake dummy promise. 但是由于我的第二个then()对此一无所知,而且仍然挂在那儿,所以我认为我需要从第一个返回,然后再得到一些假的虚拟承诺。 But I would also like to recognize this case in second then() . 但我也想在第二then()认识到这种情况。 I came up with returning $q.when('some value') from first case. 我想出从第一种情况返回$ q.when('some value')。 Here is the code: 这是代码:

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

The thing is I want to see value with which promise was resolved ({isDummy: true}), but how do I do that? 问题是我希望看到实现诺言的价值({isDummy:true}),但是我该怎么做? I get undefined in my res parameter. 我在res参数中undefined

res will be undefined here res将在这里未定义

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

because there's no data property on {isDummy: true} object. 因为{isDummy: true}对象上没有data属性。

I think the basic issue here is confusing promises with promise handlers. 我认为这里的基本问题是使承诺与承诺处理程序混淆。 The success handlers should return a value, not another promise. 成功处理程序应该返回一个值,而不是另一个诺言。 When you are in a promise success handler you are 'wrapped' by the promise mechanism which takes you returned value and passes it on to the next handler. 当您处于promise成功处理程序中时,您会被promise机制“包装”,该机制将您返回的值传递给下一个处理程序。 This means your second promise does not see the initial response but what the first promise returned. 这意味着您的第二个诺言没有看到最初的反应,而是第一个诺言返回了什么。

The value is processed as it goes along unless you pass it as is. 除非您原样传递它,否则将一直处理该值。

For example This all comes to that your line 例如,这一切都到您的行

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

Should be 应该

return {isDummy: true};

The problem is the other case, where you want to continue to a next query. 问题是另一种情况,您想继续下一个查询。 I would probably do one of the following: 1. Start in the first promise the handling (with the related logic from the first handler). 我可能会执行以下操作之一:1.从第一个promise开始处理(使用第一个处理程序中的相关逻辑)。 2. Pass on url2 and params - return({url: url2, params: params}) and handle them in the second promise. 2.传递url2和params-return({url:url2,params:params})并在第二个承诺中处理它们。

Note the promise chanins can even break in the middle, if any of the handlers rejects, following success handlers will not be called, here is a simple example (make sure you open your devtools console to see the log). 注意promise chanins甚至可以在中间中断,如果任何处理程序拒绝,则不会调用成功的处理程序, 这是一个简单的示例 (请确保打开devtools控制台以查看日志)。

Try to return any object except promise or deferred :) And its value will be passed to then . 尝试返回除promise或deferred之外的任何对象:),其值将传递给then Like this: 像这样:

return { isDummy: true };

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

From jQuery when documentation : 从jQuery的when 文档

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. 如果将单个参数传递给jQuery.when(),而不是Deferred或Promise,它将被视为已解析的Deferred,任何附加的doneCallbacks都将立即执行。 The doneCallbacks are passed the original argument. doneCallbacks传递给原始参数。

If you want code sync, you can always write a long code block in the first then. 如果要进行代码同步,则始终可以先写一个长代码块。

if you want to chain promise (Post:url1)->(Post:url2) and so on: 如果要链接诺言(Post:url1)->(Post:url2)等等:

1.The return is useless. 1.退货是没有用的。 2. Let's assume you have 2 $http promises you want to chain, both from a service called $users, for example, and they called GetUserAge and GetRelevantBars and the second query is based on the first one's results. 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*/
 }

}

hope this is understandable.. 希望这是可以理解的。

Instead of returning a dummy value and ignoring that explictly, you rather should nest and attach the second handler only to the promise that needs it: 与其返回一个虚拟值并明确忽略该值,不如将第二个处理程序嵌套并附加到需要它的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() {…});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM