Enhancing AngularJS Simple Factory - boosting the functionality of PhoneGap Storage API

Attempting to implement a "nice" feature in AngularJS with my average JS skills, I am seeking feedback on how to enhance or refactor the code below:

angular.module('App').factory("SQLService", function ($q) {

    var db = window.openDatabase("FOOD_DATABASE", app.current_version, "FOOD_DATABASE_DN", 5 * 1024 * 1024);

    // public methods
    function getCategories(){
      deferred = $q.defer();

      db.transaction(queryDB, errorCB);

      function queryDB(tx) {
        tx.executeSql('SELECT * FROM CATEGORIES', [], querySelectSuccess, errorCB);
      }

      return deferred.promise;
    }

    function getDishes(){
      deferred = $q.defer();

      db.transaction(queryDB, errorCB);

      function queryDB(tx) {
        tx.executeSql('SELECT * FROM DISHES', [], querySelectSuccess, errorCB);
      }

      return deferred.promise;
    }

    // private-like methods
    function errorCB(err) {
      alert("Error processing SQL: " + err.code);
    }

    function querySelectSuccess(tx, results) {
      var len = results.rows.length;
      var output_results = [];

      for (var i=0; i<len; i++){
        output_results.push(results.rows.item(i));
      }

      deferred.resolve(output_results);

    }

  //expose object with public methods
  return {
    getCategories: getCategories,
    getDishes: getDishes,

  };

});

I find creating a global deferred = $q.defer(); in each public function unideal. How can I refactor this to avoid that? Should I declare it as local and figure out how to pass it as an extra parameter to the querySelectSuccess callback? Any thoughts?

Answer №1

has shared the following code snippet:

function fetchUserData(){
  return promisedRequest('SELECT * FROM USERS', handleSuccess, handleError);
}

function fetchPosts(){
  return promisedRequest('SELECT * FROM POSTS', handleSuccess, handleError);
}

function handleSuccess(deferred) {
  return function(tx, results) {
    var len = results.rows.length;
    var output_data = [];

    for (var i=0; i<len; i++){
      output_data.push(results.rows.item(i));
    }

    deferred.resolve(output_data);  
  }  
}

function handleError(err) {
  alert("Error retrieving data: " + err.code);
}

function promisedRequest(query, successCB, errorCB) {
  var deferred = $q.defer();
  db.transaction(function(tx){
    tx.executeSql(query, [], successCB(deferred), errorCB);      
  }, errorCB);
  return deferred.promise;  
}

Answer №2

It's possible that I'm mistaken, but based on my initial experience with Angular, it seems like there might be something you overlooked, as I did too.

If you directly connect the view (UI) to the service/factory, then you won't need deferred and all kinds of updates because it will automatically update itself. Here's how it's done:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <style>
        .main { width: 400px; }
        .singleItem { width: 25%; display:inline-block; border: 2px dashed green; }
        .textContainer { text-align: center; }
    </style>
    <script src="angular.js"></script>
    <script >
        var myStudyModule = angular.module('myStudyModule', []);

        myStudyModule.service('myService', function ($http) {
            console.log("myService");
            var self = this;
            self.catalog = [];

            self.getData = function (parentKey, level) {
                console.log("myService.getMyData");
                var url = 'Handler1.ashx';
                if (parentKey && level)
                    url += '?parentKey=' + parentKey + '&level=' + level;
                $http.get(url).success(function (data) {
                    console.log("$http.get.success");
                    self.catalog = data;
                });
            };

            self.getData();
        });

        var myController = function ($scope, myService) {
            console.log("myController");
            $scope.myService = myService;

            $scope.MainItemClick = function (catalogItem) {
                console.log("$scope.MainItemClick");
                myService.getData(catalogItem.key, catalogItem.level + 1);
            };
        };

        myStudyModule.controller(myController);
    </script>
</head>
<body>
    <div class="main" ng-app="myStudyModule" ng-controller="myController"> 
        <div class="singleItem" ng-repeat="catalogItem in myService.catalog" ng-click="MainItemClick(catalogItem)" >
            <a class="box" href="#" >
                <img ng-src="{{ catalogItem.image }}" width="100">
                <div class="textContainer" >
                    <h4>{{ catalogItem.level }} - {{ catalogItem.name }}</h4>
                </div>
            </a>
        </div>
    </div>
</body>
</html>

By the way, I have many more self-study examples available here.

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

Exploring a JavaScript file with the power of JavaScript and HTML

I have a .js file that contains the following data (excerpt for brevity) var albums= "tracks":[ {"title":"Dunnock","mp3":"Birdsong-Dunnock.mp3", "lyrics":"The Dunnock or hedge sparrow has a fast warbling song often delivered from t ...

Filtering Dropdown List in AngularJS with a Text Input Field and a Submit Button for Filtering Option Values

After exploring , I discovered a feature that enables users to type in a text box and filter results in a pseudo-dropdown. My goal is to enhance this functionality or come up with a better approach for users to type and filter select box options, ultimate ...

The Angular function fails to execute when clicked

I am trying to trigger a new page launch when a cube is clicked using Angular. Unfortunately, my current code doesn't seem to be working as expected and nothing happens when I click the cubes. This makes me wonder if there is something wrong with my i ...

How come Google Code Beautifier suddenly ceases to function properly when combined with JQuery DatePicker?

When the Google Code Prettifier or JQuery Syntax Highlighter is used on the same page as the JQuery DatePicker, both functionalities may not work correctly. What could be causing this issue? ...

Click once to reveal, click twice to conceal the slider

I currently have a web page set up so that a single click on the text displays a slider for selecting a range of values. Now, I want to incorporate a feature where a double click will remove the slider. Below is the HTML code: <!DOCTYPE html> < ...

Create a roster of individuals who responded to a particular message

Can a roster be created of individuals who responded to a specific message in Discord? Message ID : '315274607072378891' Channel : '846414975156092979' Reaction : ✅ The following code will run: bot.on("ready", async () = ...

leveraging a callback function alongside the useState hook

I'm facing an issue with the change() function. My goal is to call the filteredData() function after the setState operation is completed. Typically, I would use a callback function for this task, but useState doesn't support callbacks. Using useE ...

Is there a way to exclude certain URLs from the service worker scope in a create react app, without the need to eject from the project?

Is there a way to remove certain URLs from a service worker scope in create-react-app without needing to eject? The service worker is automatically generated, and it seems impossible to modify this behavior without undergoing the ejection process. ...

Alter the text color once the halfway point is reached at an angle of 175 degrees

I want the text color to turn white when the background color changes to blue after reaching 50% height with a 175 degree angle. Check out this Fiddle .bg { background: linear-gradient(175deg, #e2e2e2 50%, #435289 50%); color:#000; } <div ...

The componentDidMount lifecycle method of a rendered component in a Route is not being triggered

IMPORTANT: SOLUTION PROVIDED BELOW, NO NEED TO READ THROUGH THE QUESTION I am utilizing the following Router with react-router 4 return ( <Router> <Page> <Route exact path="/" component={HomePage} /> <Route path="/c ...

Canvas displaying inaccurately (unsteady)

While working on a simple HTML5/javascript game, I encountered an unusual issue with the canvas drawings - they seem to be unstable. I have a map that needs to be drawn in a specific way: The background consists of 2 layers: the ocean and the islands. Th ...

What is the best way to create two MUI accordions stacked on top of each other to each occupy 50% of the parent container, with only their contents scrolling

I am looking to create a layout with two React MUI Accordions stacked vertically in a div. Each accordion should expand independently, taking up the available space while leaving the other's label untouched. When both are expanded, they should collect ...

Find the total value of specific keys within nested objects

I possess a shopping cart object with various products: const shopCart = { "4509563079435": { name: "product 1", price: 29.99, quantity: 2, subtotal: 59.98, }, "5678327300382": { nam ...

packages have gone AWOL in the Bitbucket pipeline

Hello everyone. I am currently working on setting up a pipeline for my nextjs-project and I've encountered a problem. I have a specific function for generating buildId # scripts/generate-build-id.js const nextBuildId = require('next-build-id&ap ...

Steps for showing an error prompt when input is invalid:

In my Vue 3 application, I have implemented a simple calculator that divides a dividend by a divisor and displays the quotient and remainder. Users can adjust any of the four numbers to perform different calculations. <div id="app"> <inp ...

Extracting the magnifying glass from the picture

After implementing a function to add a magnifying glass (.img-magnifier-glass) on button click, I am now looking to remove the glass by clicking the "cancel" button. However, I am unsure of how to write this function to interact with the "magnify" function ...

The efficiency of Ajax JSON timeouts needs improvement

Currently, I'm in the process of developing an interactive map with specific functionalities. Essentially, the user will click on a year (stored as var currentyear) and then select a country (its name stored as var thenameonly). Subsequently, an AJAX ...

Failing to complete a field in the form does not generate an error message when submitted [AngularJS]

My code is designed to display an error message if the user clicks the submit button without filling in a field. However, the functionality is currently not working as intended. <form name="loginForm" ng-submit="loginForm.$valid && login()" n ...

Is There a Way to Abandon a route and Exit in Express during a single request?

In order to ensure proper access control for the application I was developing, I structured my routing system to cascade down based on user permissions. While this approach made sense from a logical standpoint, I encountered difficulties in implementing it ...