Accepting either a synchronous or asynchronous object in a controller within the context of Angular and Ionic, based on specific conditions

Below is the controller code that I am using:

.controller('SponsorsCtrl', function ($scope, Sponsors, $http) {
    $scope.$on('$ionicView.enter', function () {
        Sponsors.all($http).then(function (data) {
                $scope.sponsors = data;
                var check = "check";
                })       
    });
})

The reason for utilizing "then" is because I am dealing with an asynchronous object. However, there is also a scenario where I may receive a synchronous object through this service: (function(){ angular .module('sponsors.services', []) .factory('Sponsors', Sponsors);

Sponsors.$inject = [];

function Sponsors() {

    var service = {
        all: all,
        allServer: allServer,
        allLocal: allLocal,
        get: get,
        getTimeStamp: getTimeStamp
    };
    return service;

    function all($http) {
        var timeDifference = (Date.now() - this.getTimeStamp());

        if (timeDifference < 600000) {
            return this.allLocal();
        }
        else {                
            return this.allServer($http);       
        }
    }

    function allServer($http) {
        return $http.get("http://dream16backend.azurewebsites.net/api/dream16/sponsors")
                    .then(function (resp) {
                        //Set localstorage, create timestamp and return the data
                        window.localStorage.setItem('sponsors', resp.data);
                        window.localStorage.setItem('sponsorsTimeStamp', Date.now());
                        var bla = JSON.parse(window.localStorage.getItem('sponsors'));
                        return bla;
                    }, function(err) {
                        console.log('ERR', err);
                    });            
    }

    function allLocal() {
        return JSON.parse(window.localStorage.getItem('sponsors'));
    }

    function get(adressId) {
        for (var i = 0; i < sponsors.length; i++) {
            if (sponsors[i].id === parseInt(sponsorId)) {
                return sponsors[i];
            }
        }
        return null;
    }

    function getTimeStamp() {           
        return window.localStorage.getItem('sponsorsTimeStamp');
    }
}

})(); In this setup, only the async call (function allServer) is functioning properly, but the sync call is failing due to:

Sponsors.all(...).then is not a function

I attempted to resolve this issue by moving the "then" functionality to the all function in the service. This change allows the sync call (function allLocal) to work, but now the async call fails. The else condition now looks like this:

else {
                this.allServer($http).then(function (data) {
                    return data;
                })
            }

And the controller has been adjusted accordingly:

.controller('SponsorsCtrl', function ($scope, Sponsors, $http) {
    $scope.$on('$ionicView.enter', function () {
        $scope.sponsors = Sponsors.all($http);
        var check = "check"; 
    });
})

I have verified that the call itself is functional (verified via test variable "bla"). Additionally, it seems that the controller executes var check = "check"; before running the async code. What could be the issue here?

Answer №1

Alright, in order to ensure that both instances of Sponsors.all() return a promise, you will need to inject $q into the service so that allLocal() can also return a promise.

function allLocal() {
    return $q.resolve(JSON.parse(window.localStorage.getItem('sponsors')));
}

Within the controller, make sure to use then():

$scope.$on('$ionicView.enter', function () {
    Sponsors.all($http).then(function(data){
       $scope.sponsors = data;
    });
    var check = "check"; 
});

Just a reminder from the comments above - there is no necessity to inject $http into the controller and pass it to the service. It would be more straightforward to inject $http directly into the service where it is needed.

Answer №2

My suggested solution would be the following. In either scenario, return a "Promise" object. This is what the allLocal function will resemble:

function allLocal() {
    var deferred = $q.defer();
    deferred.resolve(JSON.parse(window.localStorage.getItem('sponsors')));
    return deferred.promise;
}

As a result, you can now utilize .then in both synchronous and asynchronous scenarios.

Answer №3

To enhance your service, it is suggested to include the $http service within your service like so:

.factory('MyService', function ($http, $timeout,$q) {
    var service = {
            all: all,
            allServer: allServer,
            allLocal: allLocal,
            get: get,
            getTimeStamp: getTimeStamp
        };
        return service;

        function all() {
            var timeDifference = (Date.now() - this.getTimeStamp());

            if (timeDifference < 600000) {
                return this.allLocal();
            }
            else {                
                return this.allServer($http);       
            }
        }

        function allServer() {
            return $http.get("http://dream16backend.azurewebsites.net/api/dream16/sponsors")
                        .then(function (resp) {
                            //Set localstorage, create timestamp and return the data
                            window.localStorage.setItem('sponsors', resp.data);
                            window.localStorage.setItem('sponsorsTimeStamp', Date.now());
                            var bla = JSON.parse(window.localStorage.getItem('sponsors'));
                            return bla;
                        }, function(err) {
                            console.log('ERR', err);
                        });            
        }

        function allLocal() {
            var dfd = $q.defer();   //create a deferred object
            $timeout(function(){
               var localResponse = JSON.parse(window.localStorage.getItem('sponsors'));; 
               dfd.resolve(localResponse);   //resolve the localObject
            });
            return dfd.promise;  //return the promise object so controller gets the .then function
        }

        function get(adressId) {
            for (var i = 0; i < sponsors.length; i++) {
                if (sponsors[i].id === parseInt(sponsorId)) {
                    return sponsors[i];
                }
            }
            return null;
        }

        function getTimeStamp() {           
            return window.localStorage.getItem('sponsorsTimeStamp');
        }
})

Answer №4

If you're working with a service that may or may not provide a promise, you can utilize $q.when(...) to encapsulate that API call and allow $q to manage the process.

In your specific situation, simply wrap your service api like this: $q.when(Sponsors.all($http)) and use it like any other standard promise.

Take a look at https://github.com/kriskowal/q/wiki/API-Reference#promise-methods for more information.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

steps for centering an image on an ionic page

Is there a way to center an image (logo) both horizontally and vertically on the page? <ion-view hide-nav-bar="true"> <ion-content class="backgound-red "> <section class = "home-container"> <div class="row icon-row"> ...

The Jquery animate function is not compatible with the transform property

I am facing an issue with the Jquery animate function. Despite trying various solutions, I have been unable to get it to work. Below is the HTML code that I have used: <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

Troubleshooting a dysfunctional Vue.js component

I am currently facing a challenge in getting components to function properly. Interestingly, without the component, everything seems to be working fine (as per the commented code). Here is my HTML snippet: <strong>Total Price:</strong> <sp ...

Unable to extract attributes from a different model within Sails.js

I'm working on populating a customer model with attributes from the address.js model. However, when trying to post JSON using Postman, I keep getting a 500 Validation Error and struggling to pinpoint the cause of the issue. Any assistance would be gre ...

Adjust Mui Autocomplete value selection in real-time

I have implemented Mui AutoComplete as a select option in my Formik Form. <Autocomplete disablePortal options={vendors} getOptionLabel={(option) => option.vendor_company} onChange={(e, value) => {setFieldValue("vendor_id", value. ...

Is it possible to upload a file to my web application without having configured any backend system?

Currently, I am in the process of developing a landing page that includes a form where users can input their data and send an email. I have successfully implemented the form using HTML, CSS, and JavaScript, and I have even managed to incorporate the email- ...

Having trouble with Javascript fetch() not receiving the correct JSON data from the local server

My Django backend is serving JSON data, but I'm encountering some unexpected results. When using curl 127.0.0.1:8000/posts/, the response includes: [ { "title": "This is a title", "body": "Body :)", "pub_da ...

Tips for updating a specific field within an object in an array within a mongoose schema and persisting the changes

I am currently developing a website where users can sign in, create tasks, and mark them as done. I am using mongoose to work with the data, specifically saving tasks inside an array of type Task in a User model. Each task has a "done" value which is repre ...

Could somebody explain in simple terms how to correctly set up offline Google oauth2 with node.js?

When using a web browser, I follow these steps: let { code } = await this.auth2.grantOfflineAccess(); I then store the retrieved code in my database. Next, on the server side with node.js, I do the following: const { tokens } = await oauth2Client ...

Step-by-Step Guide: Crafting a Non-Ajax Popup Chat Application

Recently, I created a unique dating website with a one-to-one chat feature similar to Facebook. However, I implemented this using the ajax technique and the setInterval function in JavaScript for regular updates. Upon reflection, I believe that this appr ...

How can I show information in a Rich Textarea when an AJAX request is successful using JavaScript?

Below is the code snippet: <textarea class="textarea" id="about_us" placeholder="Place some text here" style="width: 100%; height: 100%; font-size: 14px; line-height: 18px; border: 1px solid #dddddd; padding: 10px; ...

Creating a prototype function in JavaScript

I am attempting to create a JavaScript prototype function that replicates the Python syntax of 'a' in 'abc'. The function works correctly in one example, but not in another. Can you help me identify what mistake I made? String.proto ...

Incorporating data types into a constant in Typescript/Javascript

Imagine I wanted to ensure these variables are string objects by adding a type string declaration to this variable assignment. What is the correct way to accomplish this? const { someID, someName, someAPIenvironment } = useParams(); This is what I attemp ...

Is it possible to utilize the package.json "resolutions" field to replace lodash with lodash-es?

Is it possible to use resolutions in a similar manner as dependencies, but with a different package? I'm specifically curious if this can be done with NPM or Yarn. "resolutions": { "lodash": "npm:lodash-es@^14.7.x" ...

Access the document on the desktop and open it in a new popup window

As a novice in html coding, I'm wondering if it's possible to write window size and other properties directly into the page. Let me explain. I'm currently working on a calculator and I want to run the HTML file on my desktop. Everything wor ...

Issue with datepicker functionality not operational for newly added entries in the table

@Scripts.Render("~/bundles/script/vue") <script> var vueApp = new Vue({ el: '#holiday-vue', data: { holidays: @Html.Raw(Json.Encode(Model)), tableHeader: 'Local Holidays', holidayWarning: true, dateWarning: true }, methods: ...

How can I detect a click event on an SVG element using JavaScript or jQuery?

Currently, I am developing a web application that utilizes SVG. However, I have encountered an issue: I am struggling to add a click event to each element within the SVG using jQuery. The problem arises when attempting to trigger the event; it seems like t ...

Removing and adding elements to an array in JQuery without re-indexing the array keys

My challenge involves managing a list of checkboxes. When a checkbox is clicked, a new array is appended to the main array. If a checkbox is unchecked, the corresponding array is removed without changing the index of any other array in the current array. ...

Is the JSON data not matching the file's content during validation?

After thorough testing, my JSON data appears to be functioning correctly with regular content. Here is a sample of the working JSON: Working Json { "language": "XYZ", "content": { "GEN": "this is test& ...

Step-by-step guide on displaying a modal dialog in React with the help of Bootstrap

In my project, I am working with react-16 and have used the create-react-app tool along with the vanilla bootstrap 4 library for styling (without additional components). Could someone please provide me with a reference or example where I can learn how to ...