国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

AngularJS:factory,service與provider的區(qū)別

lanffy / 1770人閱讀

摘要:首先創(chuàng)建我們的構(gòu)造函數(shù)這是一個(gè)典型的構(gòu)造函數(shù)。所以,我們首先知道的就是無論我們是否能夠在代碼里面看見,構(gòu)造函數(shù)是會(huì)返回一個(gè)對象的。

翻譯自 http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/

當(dāng)你開始使用Angular的時(shí)候,你會(huì)發(fā)現(xiàn),你總是會(huì)讓你的控制器和作用域充滿各種不必要的邏輯。你應(yīng)該早點(diǎn)意識到一個(gè)控制器應(yīng)該是很簡潔精煉的;同時(shí)大多數(shù)的商業(yè)邏輯和一些重復(fù)性的數(shù)據(jù)都應(yīng)該要存儲到服務(wù)中。一天我在Stack Overflow上看到一些問題說是考慮將重復(fù)性的數(shù)據(jù)放在控制器里,但是,這不是這不是一個(gè)控制器應(yīng)該有的目的。如果為了內(nèi)存需要,控制器就應(yīng)該在需要他們的時(shí)候?qū)嵗诓恍枰臅r(shí)候就取消掉。因此,Angular在你每次切換路由的時(shí)候,就會(huì)清理當(dāng)前的控制器。但是呢,服務(wù)為我們提供了一種長期存儲應(yīng)用數(shù)據(jù)的方式,同時(shí),也可以在不同的控制器之間統(tǒng)一的使用服務(wù)。

Angular為我們提供了三種創(chuàng)建服務(wù)的方式:

1、Factory
2、Service
3、Provider

先簡單介紹一下

一、當(dāng)使用factory來創(chuàng)建服務(wù)的時(shí)候,相當(dāng)于新創(chuàng)建了一個(gè)對象,然后在這個(gè)對象上新添屬性,最后返回這個(gè)對象。當(dāng)把這個(gè)服務(wù)注入控制器的時(shí)候,控制器就可以訪問在那個(gè)對象上的屬性了。

app.factory("MyFactory", function () {
        var _artist = "",
            service = {};

        service.getArtist = function () {
            return _artist;
        };

        return service;
    })
    .controller("myFactoryCtrl", [
        "$scope", "MyFactory",
        function ( $scope, MyFactory ) {
            $scope.artist = MyFactory.getArtist();
        }]);

二、當(dāng)使用service創(chuàng)建服務(wù)的時(shí)候,相當(dāng)于使用new關(guān)鍵詞進(jìn)行了實(shí)例化。因此,你只需要在this上添加屬性和方法,然后,服務(wù)就會(huì)自動(dòng)的返回this。當(dāng)把這個(gè)服務(wù)注入控制器的時(shí)候,控制器就可以訪問在那個(gè)對象上的屬性了。

app.service("MyService", function () {
        var _artist = "";
    
        this.getArtist = function () {
            return _artist;
        };
    })
    .controller("myServiceCtrl", [
        "$scope", "MyService",
        function ( $scope, MyService ) {
            $scope.artist = MyService.getArtist();
        }]);

三、provider是唯一一種可以創(chuàng)建用來注入到config()函數(shù)的服務(wù)的方式。想在你的服務(wù)啟動(dòng)之前,進(jìn)行一些模塊化的配置的話,就使用provider

app.provider("MyProvider", function () {

        // 只有直接添加在this上的屬性才能被config函數(shù)訪問
        this._artist = "";
        this.thingFromConfig = "";

        // 只有$get函數(shù)返回的屬性才能被控制器訪問
        this.$get = function () {
            var that = this;

            return {
                getArtist: function () {
                    return that._artist;
                },
                thingFromConfig: that.thingFromConfig
            };
        };
    })
    .config(["MyProvider", function ( MyProvider ) {
        MyProvider.thingFormConfig = "this is set in config()";
    }])
    .controller("myProviderCtrl", [
        "$scope", "MyProvider",
        function ( $scope, MyProvider ) {
            $scope.artist = MyProvider.getArtist();
        }]);
下面我們來詳細(xì)說明

為了詳細(xì)的說明這三種方式的不同之處,我們分別使用這三種方式來創(chuàng)建同一個(gè)服務(wù)。這個(gè)服務(wù)將會(huì)用到iTunes API以及promise的$q

使用factory

要?jiǎng)?chuàng)建和配置服務(wù),最普通的做法就是使用factory。就像上面簡單說明的那樣,這里也沒有太多要說明的地方,就是創(chuàng)建一個(gè)對象,然后為他添加屬性和方法,最后返回這個(gè)對象。當(dāng)把這個(gè)服務(wù)注入控制器的時(shí)候,控制器就可以訪問在那個(gè)對象上的屬性了。一個(gè)很普通的例子就像下面那樣。

首先我們創(chuàng)建一個(gè)對象,然后返回這個(gè)對象。

app.factory("MyFactory", function () {
    var service = {};
    
    return service;
});

現(xiàn)在,我們添加到service上的任何屬性,只要將MyFactory注入到控制器,控制器就都可以訪問了。

現(xiàn)在,我們添加一些私有屬性到回調(diào)函數(shù)里,雖然不能從控制器里直接訪問這些變量,但是最終我們會(huì)提供一些gettersetter方法到service上以便于我們在需要的時(shí)候修改這些屬性。

app.factory("MyFactory", [
    "$http", "$q", function ( $http, $q ) {
        var service = {},
            baseUrl = "https://itunes.apple.com/search?term=",
            _artist = "",
            _finalUrl = "";

        function makeUrl() {
            _artist = _artist.split(" ").join("+");
            _finalUrl = baseUrl + _artist + "&callback=JSON_CALLBACK";
            return _finalUrl;
        }

        return service;
    }]);

你應(yīng)該注意到了,我們沒有把這些屬性和方法添加到service對象上去。我們現(xiàn)在只是先簡單的創(chuàng)建出來,以便于待會(huì)兒使用或者修改。

baseUrl是iTunes API需要的基本URL

_artist是我們需要查找的藝術(shù)家

_finalUrl是最終向iTunes發(fā)送請求的URL

makeUrl是一個(gè)用來創(chuàng)建返回我們最終的URL的函數(shù)

既然我們的輔助變量和函數(shù)都創(chuàng)建好了,那么,就往service添加一些屬性吧。我們在service上添加的任何屬性,只要服務(wù)注入了控制器中,那么,控制器就可以訪問這些屬性。

我們要?jiǎng)?chuàng)建一個(gè)setArtist()getArtist()函數(shù)來設(shè)置以及取得藝術(shù)家的值。同時(shí),也要?jiǎng)?chuàng)建一個(gè)用于向iTunes發(fā)送請求的函數(shù)。這個(gè)函數(shù)會(huì)返回一個(gè)promise對象,當(dāng)有數(shù)據(jù)從iTunes返回的時(shí)候,這個(gè)promise對象就會(huì)執(zhí)行。如果你對Angular的promise對象還不是很了解的話,推薦你去深入了解一下。

setArtist()接受一個(gè)參數(shù)并且允許用來設(shè)置藝術(shù)家的值

getArtist()返回藝術(shù)家的值

callITunes()首先會(huì)調(diào)用makeUrl()函數(shù)來創(chuàng)建我們需要使用$http進(jìn)行請求的URL,然后使用我們最終的URL來發(fā)送請求,創(chuàng)建一個(gè)promise對象。由于$http返回了promise對象,我們就可以在請求之后調(diào)用.success.error了。然后我們處理從iTunes返回的數(shù)據(jù)或者駁回,并返回一個(gè)錯(cuò)誤消息,比如There was an error

app.factory("MyFactory", [
    "$http", "$q", function ( $http, $q ) {
        var service = {},
            baseUrl = "https://itunes.apple.com/search?term=",
            _artist = "",
            _finalUrl = "";

        function makeUrl() {
            _artist = _artist.split(" ").join("+");
            _finalUrl = baseUrl + _artist + "&callback=JSON_CALLBACK";
            return _finalUrl;
        }

        service.setArtist = function ( artist ) {
            _artist = artist;
        };

        service.getArtist = function () {
            return _artist;
        };

        service.callITunes = function () {
            var deferred = $q.defer();
            _finalUrl = makeUrl();

            $http({
                method: "JSONP",
                url: _finalUrl
            }).success(function ( data ) {
                deferred.resolve(data);
            }).error(function ( error ) {
                deferred.reject(error);
            });

            return deferred.promise;
        };

        return service;
    }]);

現(xiàn)在,我們的服務(wù)就完成了,我們可以將這個(gè)服務(wù)注入到任何的控制器了,并且,可以使用我們添加到service上的那些方法了(getArtist, setArtise, callITunes)。

app.controller("myFactoryCtrl", [
    "$scope", "MyFactory", function ( $scope, MyFactory ) {
        $scope.data = {};
        $scope.updateArtist = function () {
            MyFactory.setArtist($scope.data.artist);
        };

        $scope.submitArtist = function () {
            MyFactory.callITunes().then(function ( data ) {
                $scope.data.artistData = data;
            }, function ( error ) {
                alert(error);
            });
        };
    }]);

在上面的控制器中我們注入了MyFactory服務(wù),然后,將從服務(wù)里來的數(shù)據(jù)設(shè)置到$scope的屬性上。上面的代碼中最難的地方應(yīng)該就是你從來沒有使用過promise。由于callITunes()返回了一個(gè)promise對象,所以一旦有數(shù)據(jù)從iTunes返回,promise執(zhí)行的時(shí)候,我們就可以使用.then()方法來設(shè)置$scope.data.artistData的值了。你會(huì)注意到,我們的控制器非常簡潔,我們所有的邏輯和重復(fù)性數(shù)據(jù)都寫在了服務(wù)里面。

使用service

也許在使用service創(chuàng)建服務(wù)時(shí),我們需要知道的最重要的一件事就是他是使用new關(guān)鍵字進(jìn)行實(shí)例化的。如果你是Javascript大師,你應(yīng)該知道從代碼的本質(zhì)來思考。對于那些不了解Javascript背景的或者并不熟悉new實(shí)際做了什么的程序員,我們需要復(fù)習(xí)一下Javascript的基礎(chǔ)知識,以便于最終幫助我們理解service的本質(zhì)。

為了真正的看到當(dāng)我們使用new來調(diào)用函數(shù)的時(shí)候發(fā)生了什么,我們來創(chuàng)建一個(gè)函數(shù),并且使用new來調(diào)用他,然后,我們再看看在解釋器發(fā)現(xiàn)new的時(shí)候,他會(huì)做什么。最終結(jié)果肯定是一樣的。

首先創(chuàng)建我們的構(gòu)造函數(shù):

function Person( name, age ) {
    this.name = name;
    this.age = age;
}

這是一個(gè)典型的構(gòu)造函數(shù)。現(xiàn)在,無論我們什么時(shí)候使用new來調(diào)用這個(gè)函數(shù),this都會(huì)被綁定到新創(chuàng)建的那個(gè)對象上。

現(xiàn)在我們再在Person的原型上創(chuàng)建一個(gè)方法,以便于每一個(gè)實(shí)例都可以訪問到。

Person.prototype.sayName = function () {
    alert("My name is: " + this.name);
};

現(xiàn)在,由于我們在Person對象的原型上創(chuàng)建了sayName函數(shù),所以,Person的每一個(gè)實(shí)例都可以調(diào)用到這個(gè)方法。

既然我們已經(jīng)有了構(gòu)造函數(shù)和原型方法,那么,就來真正的創(chuàng)建一個(gè)Person的實(shí)例并且調(diào)用sayName函數(shù):

var tyler = new Person("Tyler", 23);
tyler.sayName();

所以,最終,所有的代碼合起來就是下面這個(gè)樣子:

function Person( name, age ) {
    this.name = name;
    this.age = age;
}

Person.prototype.sayName = function () {
    alert("My name is: " + this.name);
};

var tyler = new Person("Tyler", 23);
tyler.sayName();

現(xiàn)在我們來看看在使用new的時(shí)候到底發(fā)生了什么。首先你應(yīng)該注意到的是,在我們的例子中,使用了new之后,我們可以使用tyler來調(diào)用sayName方法,就好像這是一個(gè)對象一樣,當(dāng)然,tyler確實(shí)是一個(gè)對象。所以,我們首先知道的就是無論我們是否能夠在代碼里面看見,Person構(gòu)造函數(shù)是會(huì)返回一個(gè)對象的。第二,我們我們應(yīng)該知道,sayName方法是在原型上的,不是直接定義在Person對象實(shí)例上的,所以,Person返回的對象必須是通過原型委托的。用更簡單的例子說就是,當(dāng)我們調(diào)用tyler.sayName()的時(shí)候,解釋器就會(huì)說:“OK,我將會(huì)在剛創(chuàng)建的tyler對象上查找sayName函數(shù),然后調(diào)用他。等會(huì)兒,我沒有發(fā)現(xiàn)這個(gè)函數(shù),只看到了nameage屬性,讓我再檢查一下原型。哦,原來在原型上,讓我來調(diào)用他”。

下面的代碼就是你能夠想象的在Javascript里,new實(shí)際做了什么。下面的代碼是一個(gè)很基礎(chǔ)的例子,我以解釋器的視角來添加了一些注釋:

function Person( name, age ) {
    //var obj = object.create(Person.prototype);
    //this = obj;

    this.name = name;
    this.age = age;
    
    //return thisl
}

現(xiàn)在,既然知道了new做了什么,那么,使用service來創(chuàng)建服務(wù)也很容易理解了。

在使用service創(chuàng)建服務(wù)時(shí),我們需要知道的最重要的一件事就是他是使用new關(guān)鍵字進(jìn)行實(shí)例化的。與上面的例子的知識相結(jié)合,你應(yīng)該就能意識到你要把屬性和方法添加到this上,并且,服務(wù)會(huì)自動(dòng)返回this

與我們使用factory創(chuàng)建服務(wù)的方式不同,我們不需要新創(chuàng)建一個(gè)對象然后再返回這個(gè)對象,因?yàn)檎缥覀兦懊嫠岬降哪菢樱覀兪褂?b>new的時(shí)候,解釋器會(huì)自動(dòng)創(chuàng)建對象,并且代理到他的原型,然后代替我們返回。

所以,在所有的開始之前,我們先創(chuàng)建我們的私有輔助函數(shù),與我們之前使用factory創(chuàng)建的時(shí)候非常類似。現(xiàn)在我不會(huì)解釋每一行的意義了,如果你有什么疑惑的話,可以看看前面的factory的例子。

app.service("MyService", [
    "$http", "$q", function ( $http, $q ) {
        var baseUrl = "https://itunes.apple.com/search?term=",
            _artist = "",
            _finalUrl = "";

        function makeUrl() {
            _artist = _artist.split(" ").join("+");
            _finalUrl = baseUrl + _artist + "&callback=JSON_CALLBACK";
            return _finalUrl;
        }
    }]);

現(xiàn)在,我們會(huì)把可用的方法都添加到this上。

app.service("MyService", [
    "$http", "$q", function ( $http, $q ) {
        var baseUrl = "https://itunes.apple.com/search?term=",
            _artist = "",
            _finalUrl = "";

        function makeUrl() {
            _artist = _artist.split(" ").join("+");
            _finalUrl = baseUrl + _artist + "&callback=JSON_CALLBACK";
            return _finalUrl;
        }

        this.setArtist = function ( artist ) {
            _artist = artist;
        };

        this.getArtist = function () {
            return _artist;
        };

        this.callITunes = function () {
            var deferred = $q.defer();
            _finalUrl = makeUrl();

            $http({
                method: "JSONP",
                url: _finalUrl
            }).success(function ( data ) {
                deferred.resolve(data);
            }).error(function ( error ) {
                deferred.reject(error);
            });

            return deferred.promise;
        };
    }]);

現(xiàn)在,就像我們使用factory所創(chuàng)建的服務(wù)那樣,注入這個(gè)服務(wù)的任何一個(gè)控制器都可以使用setArtistgetArtistcallITunes方法了。下面是我們的myServiceCtrl,幾乎與myFactoryCtrl相同。

app.controller("myServiceCtrl", [
    "$scope", "MyService", function ( $scope, MyService ) {
        $scope.data = {};
        $scope.updateArtist = function () {
            MyService.setArtist($scope.data.artist);
        };

        $scope.submitArtist = function () {
            MyService.callITunes().then(function ( data ) {
                $scope.data.artistData = data;
            }, function ( error ) {
                alert(error);
            });
        };
    }]);

正如我之前提到的,一旦你理解了new關(guān)鍵詞做了什么,servicefactory就幾乎是相同的。

使用provider

關(guān)于provider,要記住的最重要的一件事就是他是唯一一種可以創(chuàng)建用來注入到app.config()函數(shù)的服務(wù)的方式。

如果你需要在你的應(yīng)用在別處運(yùn)行之前對你的服務(wù)對象進(jìn)行一部分的配置,那么,這個(gè)就顯得很重要了。盡管與serviceprovider類似,但是我們還是會(huì)講解一些他們的不同之處。

首先,類似的,我們設(shè)置我們的provider。下面的變量就是我們的私有函數(shù)。

app.provider("MyProvider", function () {
    var baseUrl = "https://itunes.apple.com/search?term=",
        _artist = "",
        _finalUrl = "";
    
    // 從config函數(shù)里設(shè)置這個(gè)屬性
    this.thingFromConfig = "";

    function makeUrl() {
        _artist = _artist.split(" ").join("+");
        _finalUrl = baseUrl + _artist + "&callback=JSON_CALLBACK";
        return _finalUrl;
    }
});

再說明一次,如果對上面的代碼邏輯有疑問的話,可以參考之前的列子。

你可以認(rèn)為provider有三個(gè)部分,第一部分是私有變量和私有函數(shù),這些變量和函數(shù)會(huì)在以后被修改。第二部分是在app.config函數(shù)里可以訪問的變量和函數(shù),所以,他們可以在在其他地方使用之前被修改。注意,這些變量和函數(shù)一定要添加到this上面才行。在我們的例子中,app.config()函數(shù)能夠修改的只有thingFromConfig。第三部分是在控制器里可以訪問的變量和函數(shù)。

當(dāng)使用 provider創(chuàng)建服務(wù)的時(shí)候,唯一可以讓控制器訪問的屬性和方法是在$get()函數(shù)里返回的屬性和方法。下面的代碼將$get添加到了this上面,最終這個(gè)函數(shù)會(huì)被返回。

現(xiàn)在,$get()函數(shù)會(huì)返回我們需要在控制器里訪問的函數(shù)和變量。下面是代碼例子:

this.$get = function ( $http, $q ) {
            return {
                setArtist: function ( artist ) {
                    _artist = artist;
                },
                getArtist: function () {
                    return _artist;
                },
                callITunes: function () {
                    var deferred = $q.defer();
                    _finalUrl = makeUrl();

                    $http({
                        method: "JSONP",
                        url: _finalUrl
                    }).success(function ( data ) {
                        deferred.resolve(data);
                    }).error(function ( error ) {
                        deferred.reject(error);
                    });

                    return deferred.promise;
                },
                thingOnConfig: this.thingFromConfig
            };
        };

現(xiàn)在,完整的provider就是這個(gè)樣子:

app.provider("MyProvider", [
    "$http", "$q", function ( $http, $q ) {
        var baseUrl = "https://itunes.apple.com/search?term=",
            _artist = "",
            _finalUrl = "";

        this.thingFromConfig = "";

        this.$get = function ( $http, $q ) {
            return {
                setArtist: function ( artist ) {
                    _artist = artist;
                },
                getArtist: function () {
                    return _artist;
                },
                callITunes: function () {
                    var deferred = $q.defer();
                    _finalUrl = makeUrl();

                    $http({
                        method: "JSONP",
                        url: _finalUrl
                    }).success(function ( data ) {
                        deferred.resolve(data);
                    }).error(function ( error ) {
                        deferred.reject(error);
                    });

                    return deferred.promise;
                },
                thingOnConfig: this.thingFromConfig
            };
        };

        function makeUrl() {
            _artist = _artist.split(" ").join("+");
            _finalUrl = baseUrl + _artist + "&callback=JSON_CALLBACK";
            return _finalUrl;
        }
    }]);

現(xiàn)在,與之前的servicefactory類似,只要我們把MyProvider注入到控制器里面,對應(yīng)的方法就可以使用了。下面是myProviderCtrl

app.controller("myProviderCtrl", [
    "$scope", "MyProvider", function ( $scope, MyProvider ) {
        $scope.data = {};
        $scope.updateArtist = function () {
            MyProvider.setArtist($scope.data.artist);
        };

        $scope.submitArtist = function () {
            MyProvider.callITunes().then(function ( data ) {
                $scope.data.artistData = data;
            }, function ( error ) {
                alert(error);
            });
        };

        $scope.data.thingFromConfig = MyProvider.thingOnConfig;
    }]);

正如之前提到的,使用provider來創(chuàng)建服務(wù)的目的就是為了能夠通過app.config()函數(shù)修改一些變量來傳遞到最終的項(xiàng)目中。我們來看個(gè)例子:

app.config(["MyProviderProvider", function ( MyProviderProvider ) {
    MyProviderProvider.thingFromConfig = "This sentence was set in app.config. Providers are the only service that can be passed into app.config. Check out the code to see how it works.";
}]);

現(xiàn)在,你就能看到,在provider里,thingFromConfig是空字符串,但是,當(dāng)我們在DOM里顯示的時(shí)候,他就會(huì)是我們上面所設(shè)置的字符串了。

謝謝你的閱讀,希望能夠幫助你分辨這三者的不同之處。

要查看完整的代碼例子,歡迎fork我的項(xiàng)目:https://github.com/tylermcginnis33/AngularServices 或者查看我在Stack Overflow的問題回答

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78896.html

相關(guān)文章

  • AngularJS FactoryService以及 Provider區(qū)別

    摘要:代碼代碼功夫瑜伽語法糖功夫瑜伽它是一個(gè)可注入的構(gòu)造器在中它是單例的用它在中通信或者共享數(shù)據(jù)都合適功夫瑜伽語法糖功夫瑜伽注意在里面可以不用返回東西因?yàn)闀?huì)調(diào)用關(guān)鍵字來創(chuàng)建對象。 AngularJS 的供應(yīng)商($provide) $provide 服務(wù)負(fù)責(zé)告訴 AngularJS 如何創(chuàng)建一個(gè)新的可注入的東西: 即服務(wù)。 服務(wù)會(huì)被叫做供應(yīng)商的東西來定義, 可以使用 $provide 來創(chuàng)建...

    Cristic 評論0 收藏0
  • AngularJSProvider們:ServiceFactory區(qū)別

    摘要:引言看了很多文章可能還是不太說得出中的幾個(gè)創(chuàng)建供應(yīng)商的方法到底有啥區(qū)別,啥時(shí)候該用啥,之前一直傻傻分不清楚,現(xiàn)在來總結(jié)一下。 引言 看了很多文章可能還是不太說得出AngularJS中的幾個(gè)創(chuàng)建供應(yīng)商(provider)的方法(factory(),service(),provider())到底有啥區(qū)別,啥時(shí)候該用啥,之前一直傻傻分不清楚,現(xiàn)在來總結(jié)一下。 下文中泛指統(tǒng)一用中文,英文即為特...

    jone5679 評論0 收藏0
  • AngularJs 入門(二)--模塊

    摘要:同名模塊已經(jīng)初始化的模塊保存在一個(gè)叫的緩存對象中,是模塊名,是模塊對象。調(diào)用注入器的方法執(zhí)行模塊的所有方法。檢查該注入器中是否存在指定的服務(wù)。如果是數(shù)組,最后一個(gè)必須是的構(gòu)造函數(shù),前面的就是構(gòu)造函數(shù)的參數(shù)名。 模塊 模塊是指寫Angular應(yīng)用的代碼片段,這樣可以使代碼分離開來,因此代碼會(huì)更好維護(hù),可讀和測試。還可以在module里定義代碼依賴關(guān)系,可以調(diào)用一個(gè)模塊,再在代碼中定義這個(gè)...

    Yangyang 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<