Attempting to retrieve data from ref.on() method within a factory and pass it to a controller

Having trouble extracting the value from a Firebase query in my factory to the controller. Any suggestions or ideas would be greatly appreciated!

Controller:

main.controller("mainCtrl", function($scope, totalusers){
  $scope.city = "whatever";
  $scope.total = totalusers.getusers($scope.city);
});

Factory (contains the query to retrieve the number of users with the specified Name):

app.factory("totalusers", function(FURL) {
    var gettotalusers      = {};
    gettotalusers.getusers = function(city) {
        var tusers = new Firebase(FURL + "/Users/" + city);
        var count  = 0;

        tusers.on("value", function(snapshot) {
            snapshot.forEach(function(child) {
                if (child.val().Name != undefined) {
                    count++;
                }
            });
            var total = count;
            return total;
        });

    }
    return gettotalusers;
});

If you have any insights or suggestions, feel free to share. Thanks in advance! ;)

Answer №1

To retrieve the firebase value asynchronously, ensure that the count value remains at 0 when assigned to the total, which is then promptly returned. Utilize the $q service to establish a promise and resolve it upon receiving the firebase callback.

app.factory("totalusers", function(FURL, $q){
  var gettotalusers = {};
  gettotalusers.getusers = function(city){
    var tusers = new Firebase(FURL + "/Users/" + city);
    var count = 0;
    var deferred = $q.defer();

    tusers.on("value", function(snapshot){
      snapshot.forEach(function(child) {
        if(child.val().Name != undefined){
          count++;
        }
      });
      deferred.resolve(count);
    });

    return deferred.promise;
  }
  return gettotalusers;
});

In your controller, refrain from directly assigning the result. Instead, implement it within a promise handler method like this:

main.controller("mainCtrl", function($scope, totalusers){
  $scope.city = "whatever";
  totalusers.getusers($scope.city).then(
    function(total) {
      $scope.total = total;
    },
    function(err) {
      // handle error
    }
  );
});

For further information, refer to the $q documentation and familiarize yourself with the concept of promises. https://docs.angularjs.org/api/ng/service/$q

You can also consider refining your count using a more functional approach with filter and reduce:

var total = snapshot
  .filter(function(item) { return child.val().Name !== undefined })
  .reduce(function(acc, curr) {
    return acc + curr;
  }
);

Answer №2

Avoid using ref.on() in this particular situation as it can result in continuous synchronization of the node even after the function has completed its execution. It is recommended to utilize ref.off(), or better yet, opt for ref.once(). If you are working with the latest version of Firebase, this method returns a promise, eliminating the need for $q.

app.factory("totalusers", function(FURL) {
    var gettotalusers = {};

    gettotalusers.getusers = function(city) {
        var tusers = new Firebase(FURL + "/Users/" + city);

        return tusers.orderByChild("Name")
                     .startAt(false)
                     .once("value")
                     .then(function(snapshot) {
            return snapshot.numChildren();
        });
    };

    return gettotalusers;
});

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

Passing values dynamically to a JavaScript function within a Chrome extension using Python at runtime

I have encountered a unique challenge in my automation work, which I detailed in this query It's important to note that I am utilizing Python with Selenium WebDriver As I navigate through a series of changes and obstacles, I find myself exploring th ...

Create a visual representation of an image by sketching a detailed line profile using HTML5's

I am attempting to create an intensity profile for an image, using the x-axis as the line's length on the image and the y-axis as the intensity values along the length of the line. How can I achieve this on an HTML5 canvas? I have tried the code below ...

Retrieve all visible rows using the AngularJS UI-scroll feature

As of now, I have integrated angular-ui/ui-scroll to dynamically load items into a table. Is there a method available to retrieve the visible items that are currently being rendered on the UI using ui-scroll? I have been utilizing adapter.topVisible and ...

Loading an animated SVG sprite file in real-time

Recently, I received an SVG sprite file from our designers to use in my app. The specified convention is to load the sprite at the top of the <body> element and then render icons using a specific code snippet: <svg class="u-icon-gear-dims"> ...

What is the process for monitoring a property in Angular?

Seeking clarification on Angular - is it possible to detect property value changes within the same class? import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html', ...

Is there a way to verify the visibility of an element in Protractor?

Currently, I am utilizing Protractor for conducting my comprehensive end-to-end tests. A few elements have been configured with ng-show attributes. Would someone kindly advise me on how to validate whether these elements are visible or not using Protracto ...

Which library should be connected in order to utilize JSONLoader, OrbitControls, and AnimationAction?

When looking for a Three.js library that supports JSONLoader, OrbitControls, and AnimationAction simultaneously, the choice can be challenging due to the variety of options available. The code snippet below showcases an attempt to incorporate these three f ...

Enhance Your Internet Explorer Experience with AngularJS Blob URL Integration

Reviewing the following code snippet (taken from another source): var module = angular.module('myApp', []); module.controller('MyCtrl', function ($scope){ $scope.json = JSON.stringify({a:1, b:2}); }); module.directive('myDow ...

jQuery's .validate() function is not compatible with table rows that are created dynamically

I'm currently working on implementing the jQuery validation plugin to ensure that all inputs in my table are restricted between 0 and 10. Each row of the table is dynamically generated by Javascript. Below is my HTML table and JS code for adding a row ...

Ways to adjust the color of a div

I'm currently working on an app using Angular.js and HTML, but I've hit a roadblock. There's a dropdown at the top, and when it changes, I want to adjust the background color of certain cells as shown in this image: https://i.sstatic.net/Ov ...

JavaScript Enigma: Instantiate 2 Date variables with identical values, yet they ultimately display distinct dates on the calendar

I need some help understanding something in my screenshot. Although both tmpStart and itemDate have been assigned the same numeric value, they display different calendar dates. start = 1490683782833 -> tmpStart = "Sun Mar 26 2017 16:51:55 GMT+ ...

Selecting Segmented Button Options using SAPUI5

In my custom SAUI5 application, I have implemented two Segmented button items - Delivery and Collection. To differentiate between the two buttons and determine which one is clicked, I aim to pass "D" as a flag for Delivery and "C" as a flag for Collectio ...

Troubleshooting IE compatibility for $.trim() jQuery functionality

Having trouble with $.trim() not working in IE but works fine in Firefox. Any ideas why this might be happening? Thanks. $('#GuestEmailAddress').on('blur', function () { var $inputValue = $(this).val(); ...

Is it feasible to dynamically incorporate various versions of Bootstrap within the head tag?

The CMS I'm currently working with has a strict dependency on a specific version of Bootstrap. However, there are features from Bootstrap 3.3.6 that I need based on the page being loaded in the browser. I initially considered using JavaScript or jQue ...

Make sure to wait for the fetch response before proceeding with the for loop in JavaScript using Node.js

I am facing an issue with my function that connects to a SOAP web service. The problem arises from the fact that the web service has limited connections available. When I use a for or foreach loop to search through an array of items in the web service, aro ...

Trouble with script initiation during Ajax postback

I am currently developing a website that displays tiles of varying heights based on the content inserted. To ensure all tiles have the same height, I implemented the following script in the header: function BindEvents() { $(window).load(function () ...

Differences Between React Prop Types and Typescript in Front-End

I'm considering incorporating TypeScript into my project. Would this render the use of prop-types in React unnecessary? With prop-types, I find myself having to manually define types, but TypeScript would eliminate this step. Am I on the right track? ...

Retrieve the location of the selected element

We are faced with the challenge of determining the position of the button clicked in Angular. Do you think this is achievable? Our current setup involves an ng-grid, where each row contains a button in column 1. When the button is clicked, we aim to displ ...

What is the best way to continuously add strings to an existing string within a loop?

When attempting the code below, I am receiving an empty string as output. var jsObj2 = { "key1": "value3", "key4": "value4" }; var c = ''; for (var key in jsObj2) { c.concat(key + ': ' + js ...

Getting just the outer edges of intricate BufferGeometry in Three.js

Currently, I am immersed in a project that involves zone creation and collision detection using Three.js. The primary objective is for my application to effectively manage collisions and produce a BufferGeometry as the final output. My aim is to visually r ...