return语句和deferred之间的区别是什么?用$http(req)在angularJS中解析

时间:2022-04-12 11:01:40

I have observed two different varieties of $http(req) in production code.

我在产品代码中观察到了两种不同的$http(req)。

sampleApp.factory('BrandService', function($http, $q) {

    var BrandService =  {};
    var BrandList = [];

    BrandService.GetBrands = function() {
        var Info ={};       
        Info.Action = "GET";
        Info = JSON.stringify (Info);

        var req = {
            url: BrandURL,
            method: 'POST',
            headers: { 'Content-Type': 'application/json'},
            data: Info
        };

        if ( BrandList.length == 0 ) {
            return $http(req).then(function (response) {
                BrandList = response.data
                return BrandList;
            });
        }
        else {
           return $q.when(BrandList);
        }
    }
    return BrandService;
});

sampleApp.factory('BrandService', function($http) {

        var BrandService =  {};
        var BrandList = [];

        BrandService.GetBrands = function() {
        var req = {
            method: 'POST',
            url: 'BrandURL',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            data: "action=GET"
        };  
        var defer = $q.defer();
        $http(req).then(function(response) {
            BrandList = response.data
            defer.resolve(BrandList);
        }, function(error) {
            defer.reject("Some error");
        });
        return defer.promise;
    }
});

In one they are using return statement directly, in other they are using defer.resolve. I want to understand the difference between two?

一个是直接使用return语句,另一个是使用deferred .resolve。我想知道两者的区别吗?

Are they both same? If not, which one to prefer when?? Also why they are not handling error in first case?

他们都是相同的吗?如果没有,那该选择什么时候呢?为什么他们不处理第一种情况下的错误?

3 个解决方案

#1


1  

TL;DR

Affectively they are both the same, only difference is that:

情感上他们都是一样的,唯一的区别是:

In the first example you're wrapping the value of the promise in itself by returning it inside.

在第一个例子中,你将承诺的价值通过返回来包装。

In the second example you're creating a new promise and wrapping the value of the first promise in the new one, and returning the new one instead.

在第二个例子中,您正在创建一个新的承诺,并将第一个承诺的值包装在新的承诺中,并返回新的承诺。


Overview

Angular's $http returns a promise, the .then() resolves that promise.

angle的$http返回一个承诺,然后()解析这个承诺。


Some examples

Lets take this as an example:

让我们以这个为例:

// this is in data/users.json
{
    "users": [{
        "name": "Nikola Tesla",
        "specialty": "Electricity"
    },{
        "name": "Chris Hadfield",
        "specialty": "Space"
    }]
}

First lets discuss a bare promise:

首先让我们讨论一个承诺:

function allUsers() {
    return $http.get('data/users.json');
}

allUsers().then(function (response) {
    console.debug(users);
    /*
        output:

        response: {
            header: {....},
            data: {
                "users": [....]
            },
            status: {.....}

        }
     */
});

as seen here

正如我们所见

Then lets return from the promise:

那么让我们从承诺中回来:

function allUsers() {
    return $http.get('data/users.json').then(function (response) {
        return response.data;
    });
}

allUsers().then(function (users) {
    console.debug(users);
    /*
        output:

        "users": [......]
     */
});

Here you're returning the value from within the promise so when it gets resolved, the value you returned would be the success value of that promise.

这里你从承诺中返回值,当它被解析时,你返回的值就是承诺的成功值。

The deffered promise would return the same as returning directly from inside, the difference is that you resolve the first promise then you extract the value, wrap it in another promise, in this case you would be returning the differed -new- promise that you just created.

得到的承诺和直接从内部返回一样,不同之处在于,你解决了第一个承诺然后提取价值,用另一个承诺包起来,在这种情况下,你将返回不同的-新的-你刚刚创造的承诺。

BTW, you can get the promise errors if you return directly from it like this:

顺便说一下,如果你直接从这里返回,你可以得到承诺错误:

function allUsers() {
    return $http.get('data/users.json').then(function (response) {
        return response.data;
    }, function (error) {
        return $q.reject({msg: 'there is an error here', error: error});
    });
}

allUsers().then(function (users) {
    console.debug(users);
    /*
        output:

        "users": [......]
     */
}, function (error) {
    console.debug(error);
    /*
        output:

        "msg": 'there is an error here',
        error: {.....}
     */
});

My 2 cents

I prefer going with the first example (returning from within the promise) simply because:

我更喜欢第一个例子(从承诺中返回),因为:

  • It's easier to read.
  • 更容易阅读。
  • You don't need to get messy with creating a new promise.
  • 你不需要在创造一个新的承诺时弄得一团糟。

However, you can use both interchangeably, so go nuts with either!

然而,你可以交替使用这两个词,所以不管用哪个词都要疯狂!

Moral of the story

故事的寓意

Both Criss Hadfield and Nikola Tesla are awesome, and they both get the job done :)

克里斯·哈德菲尔德和尼古拉·特斯拉都很棒,他们都完成了任务:

#2


1  

Both return promises, but the 1st one (return $http(req)) is the better option.

两者都有返回承诺,但是第一个(返回$http(req))是更好的选择。

Look it this article to see common promises mistakes, and the solutions.

看看这篇文章,看看常见的承诺错误和解决方案。

The 2nd one is used to manipulate the data, and resolve / reject a new promise, but it should be converted to a promises chain like the 1st, because every resolved promise return a new promise with it's resolved value.

第二个承诺用于处理数据,并解析/拒绝一个新的承诺,但是它应该转换成一个承诺链,就像第一个承诺一样,因为每个被解析的承诺都返回一个具有其解析值的新承诺。

Instead of this:

而不是:

    var defer = $q.defer();
    $http(req).then(function(response) {
        BrandList = response.data
        defer.resolve(BrandList);
    }, function(error) {
        defer.reject("Some error");
    });
    return defer.promise;

Do this:

这样做:

    return $http(req).then(function(response) {
        return response.data
    }, function(error) {
        return $q.reject("some error");
    });

#3


0  

In the first case the service will only make an $http request if BrandList is empty, otherwise it returns the list. The second case will always make an $http request. In both cases a promise is returned.

在第一种情况下,如果BrandList为空,服务只发出$http请求,否则返回列表。第二种情况总是发出$http请求。在这两种情况下,承诺都会得到回报。

Request errors are not not handled in the first case since the second parameter in .then() was not defined like in the second.

在第一种情况下不处理请求错误,因为then()中的第二个参数不像第二个参数那样定义。

While both get the job done, it seems the first is a better since it doesn't make additional http calls once BrandList has been filled. One note though, the first case might still make multiple http calls until one of them resolves. Also if BrandList is actually zero, it will always make an http call.

虽然两者都完成了这项工作,但是第一个似乎更好,因为在填写完BrandList之后,它不会再进行额外的http调用。不过有一点需要注意,第一种情况仍然可能进行多个http调用,直到其中一个解决。如果BrandList实际上是零,它总是会发出一个http调用。

#1


1  

TL;DR

Affectively they are both the same, only difference is that:

情感上他们都是一样的,唯一的区别是:

In the first example you're wrapping the value of the promise in itself by returning it inside.

在第一个例子中,你将承诺的价值通过返回来包装。

In the second example you're creating a new promise and wrapping the value of the first promise in the new one, and returning the new one instead.

在第二个例子中,您正在创建一个新的承诺,并将第一个承诺的值包装在新的承诺中,并返回新的承诺。


Overview

Angular's $http returns a promise, the .then() resolves that promise.

angle的$http返回一个承诺,然后()解析这个承诺。


Some examples

Lets take this as an example:

让我们以这个为例:

// this is in data/users.json
{
    "users": [{
        "name": "Nikola Tesla",
        "specialty": "Electricity"
    },{
        "name": "Chris Hadfield",
        "specialty": "Space"
    }]
}

First lets discuss a bare promise:

首先让我们讨论一个承诺:

function allUsers() {
    return $http.get('data/users.json');
}

allUsers().then(function (response) {
    console.debug(users);
    /*
        output:

        response: {
            header: {....},
            data: {
                "users": [....]
            },
            status: {.....}

        }
     */
});

as seen here

正如我们所见

Then lets return from the promise:

那么让我们从承诺中回来:

function allUsers() {
    return $http.get('data/users.json').then(function (response) {
        return response.data;
    });
}

allUsers().then(function (users) {
    console.debug(users);
    /*
        output:

        "users": [......]
     */
});

Here you're returning the value from within the promise so when it gets resolved, the value you returned would be the success value of that promise.

这里你从承诺中返回值,当它被解析时,你返回的值就是承诺的成功值。

The deffered promise would return the same as returning directly from inside, the difference is that you resolve the first promise then you extract the value, wrap it in another promise, in this case you would be returning the differed -new- promise that you just created.

得到的承诺和直接从内部返回一样,不同之处在于,你解决了第一个承诺然后提取价值,用另一个承诺包起来,在这种情况下,你将返回不同的-新的-你刚刚创造的承诺。

BTW, you can get the promise errors if you return directly from it like this:

顺便说一下,如果你直接从这里返回,你可以得到承诺错误:

function allUsers() {
    return $http.get('data/users.json').then(function (response) {
        return response.data;
    }, function (error) {
        return $q.reject({msg: 'there is an error here', error: error});
    });
}

allUsers().then(function (users) {
    console.debug(users);
    /*
        output:

        "users": [......]
     */
}, function (error) {
    console.debug(error);
    /*
        output:

        "msg": 'there is an error here',
        error: {.....}
     */
});

My 2 cents

I prefer going with the first example (returning from within the promise) simply because:

我更喜欢第一个例子(从承诺中返回),因为:

  • It's easier to read.
  • 更容易阅读。
  • You don't need to get messy with creating a new promise.
  • 你不需要在创造一个新的承诺时弄得一团糟。

However, you can use both interchangeably, so go nuts with either!

然而,你可以交替使用这两个词,所以不管用哪个词都要疯狂!

Moral of the story

故事的寓意

Both Criss Hadfield and Nikola Tesla are awesome, and they both get the job done :)

克里斯·哈德菲尔德和尼古拉·特斯拉都很棒,他们都完成了任务:

#2


1  

Both return promises, but the 1st one (return $http(req)) is the better option.

两者都有返回承诺,但是第一个(返回$http(req))是更好的选择。

Look it this article to see common promises mistakes, and the solutions.

看看这篇文章,看看常见的承诺错误和解决方案。

The 2nd one is used to manipulate the data, and resolve / reject a new promise, but it should be converted to a promises chain like the 1st, because every resolved promise return a new promise with it's resolved value.

第二个承诺用于处理数据,并解析/拒绝一个新的承诺,但是它应该转换成一个承诺链,就像第一个承诺一样,因为每个被解析的承诺都返回一个具有其解析值的新承诺。

Instead of this:

而不是:

    var defer = $q.defer();
    $http(req).then(function(response) {
        BrandList = response.data
        defer.resolve(BrandList);
    }, function(error) {
        defer.reject("Some error");
    });
    return defer.promise;

Do this:

这样做:

    return $http(req).then(function(response) {
        return response.data
    }, function(error) {
        return $q.reject("some error");
    });

#3


0  

In the first case the service will only make an $http request if BrandList is empty, otherwise it returns the list. The second case will always make an $http request. In both cases a promise is returned.

在第一种情况下,如果BrandList为空,服务只发出$http请求,否则返回列表。第二种情况总是发出$http请求。在这两种情况下,承诺都会得到回报。

Request errors are not not handled in the first case since the second parameter in .then() was not defined like in the second.

在第一种情况下不处理请求错误,因为then()中的第二个参数不像第二个参数那样定义。

While both get the job done, it seems the first is a better since it doesn't make additional http calls once BrandList has been filled. One note though, the first case might still make multiple http calls until one of them resolves. Also if BrandList is actually zero, it will always make an http call.

虽然两者都完成了这项工作,但是第一个似乎更好,因为在填写完BrandList之后,它不会再进行额外的http调用。不过有一点需要注意,第一种情况仍然可能进行多个http调用,直到其中一个解决。如果BrandList实际上是零,它总是会发出一个http调用。