Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
How to avoid calling this method twice?
Message
Information générale
Forum:
Javascript
Catégorie:
Autre
Divers
Thread ID:
01611738
Message ID:
01611861
Vues:
39
I think my current code is almost the same as you showed - can you spot the difference?
(function () {
    'use strict';
    
    var app = angular.module('sysMgrApp');

    app.factory('invoicesService', ['$http', '$q', function($http, $q) {

        var metaData = null;
       
        var getMetaData = function () {

            var deferred = $q.defer();

            if (angular.isObject(metaData))
                deferred.resolve(metaData);
            else {
            
                $http.get('/api/invoices/metadata')
                    .success(function (data) {
            
                        metaData = data;
                        deferred.resolve(data);
                    })
                    .error(function (data, status, header, config) {
            
                        deferred.reject(status);
                    });
            }
            
            return deferred.promise;
        };

        var getInvoices = function(queryRequest) {
            var deferred = $q.defer();
            $http.get('/api/invoices', { params: queryRequest })
                .success(function(data) {
                    deferred.resolve(data);
                })
                .error(function(data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var getAccountInvoices = function (queryRequest) {
            var deferred = $q.defer();
            $http.get('/api/invoices/getAccountInvoices', { params: queryRequest })
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var processPayments = function (transactionObject) {
            var deferred = $q.defer();
            $http.post('/api/invoices/processPayments',transactionObject )
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var getAccountInvoices = function (queryRequest) {
            var deferred = $q.defer();
            $http.get('/api/invoices/getAccountInvoices', { params: queryRequest })
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var getInvoicesToBePaid = function (queryRequest) {
            var deferred = $q.defer();
            $http.get('/api/invoices/getInvoicesToBePaid', { params: queryRequest })
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var getInvoice = function(id) {
            var deferred = $q.defer();
            $http.get('/api/invoices/' + id)
                .success(function(data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var createInvoice = function(invoice) {
            var deferred = $q.defer();
            $http.post('/api/invoices', invoice)
                .success(function(data) {
                    deferred.resolve(data);
                })
                .error(function(data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        var saveInvoice = function(invoice) {
            var deferred = $q.defer();
            $http.put('/api/invoices', invoice)
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, header, config) {
                    deferred.reject(data, status);
                });
            return deferred.promise;
        };

        var deleteInvoice = function(invoiceNo) {
            var deferred = $q.defer();
            $http.delete('/api/invoices/' + invoiceNo)
                .success(function(data) {
                    deferred.resolve(data);
                })
                .error(function(data, status, header, config) {
                    deferred.reject(status);
                });
            return deferred.promise;
        };

        return {
            getMetaData: getMetaData,      
            getInvoices: getInvoices,
            getAccountInvoices: getAccountInvoices,
            getInvoicesToBePaid: getInvoicesToBePaid,
            getInvoice: getInvoice,
            createInvoice: createInvoice,
            saveInvoice: saveInvoice,
            deleteInvoice: deleteInvoice,
            processPayments: processPayments
        };
    }]);
})();
And the way I call it in 2 controllers:
var init = function () {
                    $scope.showForm = false;
                    $scope.disableAction = false;
                    $scope.isEditLoading = false;

                    $scope.isApplyFeesLoading = false;

                    if ($stateParams.id) {
                        $scope.acctNameHash = $stateParams.id;
                        $scope.transactionObject.accountNameHash = $scope.acctNameHash;
                    }
                    $scope.applyFeesTable = searchScreenService.getTable('Invoice_No', [
                   
                    { name: 'Invoice_No', displayName: resourceFactory.getResource('Labels', 'invoiceX').format('#'), width: 12 },
                    { name: 'Descrip', displayName: resourceFactory.getResource('Labels', 'descrip'), width: 17 },
                    { name: 'LastTransactionDate', displayName: resourceFactory.getResource('Labels', 'lastTransactionDate'), width: 33 },
                    { name: 'Balance', displayName: resourceFactory.getResource('Labels', 'balance'), width: 13 },
                    { name: 'Fee', displayName: resourceFactory.getResource('Labels', 'amount'), width: 16 },
                    ]);
                    $scope.applyFeesTable.pageSize = 10000;

                    invoicesService.getMetaData().then(function (data) {
                        $scope.invoicesMetaData = data;                        
                    });
                    getInvoices();
                    //if (angular.isDefined($scope.$parent.showSearch) && $scope.$parent.showSearch) {
                    //    window.console && console.log ('showSearch defined and true, switching to false...')
                    //    $scope.$parent.showSearch = false;
                    //}
                };
and practically identical code for the other form.

Now, these two forms are partial views defined in the edit form this way:
 <div class="col-lg-3 col-md-3 panel-container">
                            <ul class="nav nav-pills nav-stacked">
                                <li class="active">
                                    <a data-toggle="pill"
                                       href="#general" ng-class="{true: 'invalid-tab', false: ''}[form.editAccountGeneral.$invalid]">@Labels.general</a>
                                </li>
                                <li><a data-toggle="pill" href="#contact" ng-class="{true: 'invalid-tab', false: ''}[form.editContactForm.$invalid]">@Labels.contact</a></li>
                                <li ng-show="!isNew"><a data-toggle="pill" href="#invoices">@Labels.invoices</a></li>

                                <li ng-show="!isNew"><a data-toggle="pill" href="#invoicesToBePaid">    @Labels.payInvoices</a></li>

                                <li ng-show="!isNew"><a data-toggle="pill" href="#applyFees" ng-class="{true: 'invalid-tab', false: ''}[form.applyFees.$invalid]">    @Labels.applyFees</a></li>

                                <li><a data-toggle="pill" href="#userDefined" ng-class="{true: 'invalid-tab', false: ''}[form.editAccountUserDefinedForm.$invalid]">@Labels.userDefined</a></li>
                                <li><a data-toggle="pill" href="#security" ng-class="{true: 'invalid-tab', false: ''}[form.editAccountSecurityForm.$invalid]">@Labels.securityRestrictions</a></li>
                                <li><a data-toggle="pill" href="#web" ng-class="{true: 'invalid-tab', false: ''}[form.editAccountWebForm.$invalid]">@Labels.web</a></li>
                            </ul>
                        </div>

                        <div class="col-lg-9 col-md-9 panel-container">
                            <div class="tab-content">
                                <div class="tab-pane active" id="general">
                                    @Html.Partial("EditAccountGeneral")
                                </div>

                                <div class="tab-pane" id="contact">
                                    @Html.Partial("EditAccountContact")
                                </div>

                                <div class="tab-pane" id="invoices" ng-controller="invoicesCrudController">
                                    @Html.Partial("../Invoices/EditAccountInvoices")
                                </div>

                                <div class="tab-pane" id="invoicesToBePaid" ng-controller="invoicesToBePaidCrudController">
                                    @Html.Partial("../Invoices/PayInvoices")
                                </div>

                                <div class="tab-pane" id="applyFees" ng-controller="applyFeesController">
                                    @Html.Partial("../Invoices/ApplyFees")
                                </div>

                                <div class="tab-pane" id="userDefined">
                                    @Html.Partial("EditAccountUserDefined")
                                </div>
                                <div class="tab-pane" id="security">
                                    @Html.Partial("EditAccountSecurity")
                                </div>
                                <div class="tab-pane" id="web">
                                    @Html.Partial("EditAccountWeb")
                                </div>
                            </div>
                        </div>
The problem here that all tabs are already in the form as partial views. We tried to use ui-view instead (and I even got some help from our AngularJs instructor) but so far our attempts were unsuccessful.

I think if we resolve that problem (e.g. will be able to use ui-view instead), then I would not have that problem of hitting the service twice.


>That approach works - I use it all the time to cache data. if it doesn't you likely have a logic error somewhere in determining whether the data is already present or you're not storing the data properly in a persistent place where it survives.
>
>Your service looks wrong in a number of ways - I don't know how you're accessing it but you wouldn't be able to even call your getMetaData function on the service since its private.
>
>This is how I would set this up:
>
>
>app.factory('invoicesService', ['$http', '$q', function($http, $q) {
> 
>       // Interface
>       var service = { 
>                metaData: null,      
>                getMetaData: getMetaData
>       }
>       return service;
>
>       // Implementation
>
>        function getMetaData() {
>            var deferred = $q.defer();
>
>            if (service.metaData)
>                deferred.resolve(service.metaData);
>            else {
>                $http.get('/api/invoices/metadata')
>                    .success(function (data) {
>                        service.metaData = data;
>                        deferred.resolve(data);
>
>                    })
>                    .error(function (data, status, header, config) {
>                        deferred.reject(status);
>                    });
>            }
>            return deferred.promise;
>        };
>
>}
>
>
>You don't have to make the metaData public, but my guess is that's what you actually want so it stays accessible and updateable by external code.
>
>+++ Rick ---
>
>>Nice article. We use the first approach in our code.
>>
>>I tried what you suggested (e.g. my new code is
>>
>>
>>app.factory('invoicesService', ['$http', '$q', function($http, $q) {
>>
>>        var metaData = null;
>>
>>        var getMetaData = function () {
>>            var deferred = $q.defer();
>>
>>            if (angular.isObject(metaData))
>>                deferred.resolve(metaData);
>>            else {
>>                $http.get('/api/invoices/metadata')
>>                    .success(function (data) {
>>                        metaData = data;
>>                        deferred.resolve(data);
>>
>>                    })
>>                    .error(function (data, status, header, config) {
>>                        deferred.reject(status);
>>                    });
>>            }
>>            return deferred.promise;
>>        };
>>
>>but I still got hit of my API controller's method twice. I'm going to look into Viv's idea now.
>>
>>>You need to return a promise even if you return the cached data.
>>>
>>>So define your deferred at the top of the code then to return the cached data:
>>>
>>>
>>>if (angular.isObject(metaData)) {
>>>      deferred.resolve(metaData);
>>>     return deferred.promise;
>>>}
>>>
>>>
>>>This way you get the same data back regardless of whether the data was returned from the AJAX call or from the cached data.
>>>
>>>You might want to read this:
>>>http://weblog.west-wind.com/posts/2014/Oct/24/AngularJs-and-Promises-with-the-http-Service
>>>
>>>which explains some of the mechanics behind this...
>>>
>>>+++ Rick ---
>>>>
>>>
>>>
>>>Define your $q.defer() before the first call then deferred.resolve(metaData); return deferred.promise() with the cached data and return the promise in the if block.
>>>
>>>+++ Rick ---
>>>
>>>>Hi everybody,
>>>>
>>>>I have two pages in the same form that need to access the same data.
>>>>
>>>>Each of the pages is controlled by its own controller and both have this code in the init:
>>>>
>>>>
>>>>invoicesService.getMetaData().then(function (data) {
>>>>                        $scope.invoicesMetaData = data;
>>>>
>>>>                    });
>>>>
>>>>So, I want to somehow adjust the service code to not invoke the method twice. Here is what I attempted to do but it's not working:
>>>>
>>>>
>>>>app.factory('invoicesService', ['$http', '$q', function($http, $q) {
>>>>
>>>>        var metaData = null;
>>>>
>>>>        var getMetaData = function () {
>>>>            if (angular.isObject(metaData))
>>>>                return metaData;
>>>>
>>>>            var deferred = $q.defer();
>>>>            $http.get('/api/invoices/metadata')
>>>>                .success(function (data) {
>>>>                    metaData = data;
>>>>                    deferred.resolve(data);
>>>>                    
>>>>                })
>>>>                .error(function (data, status, header, config) {
>>>>                    deferred.reject(status);
>>>>                });
>>>>            return deferred.promise;
>>>>        };
>>>>
>>>>I still get 2 hits in my API controller. Do you see how should I change the above to avoid the second call after the first one was already made?
>>>>
>>>>Thanks in advance.
If it's not broken, fix it until it is.


My Blog
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform