What is the most effective way to receive notifications when an OAuth response has been received?

I have implemented Facebook and Google sign in using ionic with Firebase. My setup includes 2 services - FirebaseService.js, AppService.js, and a controller dashboard.js. I am trying to receive the OAuth response in the controller.

What would be the most efficient way to achieve this? I have encountered similar scenarios before and I am looking for an optimal solution.

In my previous approach, I utilized a notifier (called when data is available) and listener:

/** notify for Auth data response */
this.authDataAvailable = function() {
    $rootScope.$emit("auth-data-available");
}
/** subscribe to this listener when the aggregated data response is available */
this.authDataAvailableListener = function(scope, callback, isDestroy) {
    var handler = $rootScope.$on("auth-data-available", callback);
    if (isDestroy)
        scope.$on("$destroy", handler);
}

/** subscribing to the above listener */
$scope.authDataResponseListener($scope, function responseAvailable() {
    //auth response available at this point
}, true);

FirebaseService.js

function FirebaseService($q) {
    this.appRef;
    this.authData;

    this.getRef = function() {
        return this.appRef;
    }
    this.authWithOAuthPopup = function(type) {
        var deferred = $q.defer();
        this.appRef = new Firebase("https://lola.firebaseio.com");
        this.appRef.authWithOAuthPopup(type, function(error, authData) {
            if (error) {
                this.authError = error;
                switch (error.code) {
                    case "INVALID_EMAIL":
                        console.log("The specified user account email is invalid.");
                        break;
                    case "INVALID_PASSWORD":
                        console.log("The specified user account password is incorrect.");
                        break;
                    case "INVALID_USER":
                        console.log("The specified user account does not exist.");
                        break;
                    default:
                        console.log("Error logging user in:", error);
                }
                deferred.resolve(this.authError);
            } else {
                this.authData = authData;
                console.log("Authenticated successfully with payload:", authData);
                deferred.resolve(this.authData);
            }
        });
                deferred.promise;
    }

    /**
     * Write or replace data to a defined path, like messages/users/<username>
     */
    this.set = function(child, obj) {
        var childRef = this.appRef.child(child);
        childRef.set(obj);
    }

    return {
        getRef: this.getRef,
        authWithOAuthPopup: this.authWithOAuthPopup
    }
}
angular.module("starter.services", []).service('FirebaseService', FirebaseService);

AppService.js

function AppService(FirebaseService, $rootScope) {
    this.authData;

    /** notify for Auth data response */
    this.authDataAvailable = function() {
        $rootScope.$emit("auth-data-available");
    }
    /** subscribe to this listener when the aggregated data response is available */
    this.authDataAvailableListener = function() {
        var handler = $rootScope.$on("auth-data-response", callback);
        if (isDestroy)
            scope.$on("$destroy", handler);
    }

    this.authenticateWithGoogle = function() {
        this.authData = FirebaseService.authWithOAuthPopup("google");
        this.authDataAvailable();
        console.log(this.authData.google.displayName);
    }

    this.authenticateWithFacebook = function() {
        this.authData = FirebaseService.authWithOAuthPopup("facebook");
        this.authDataAvailable();
        console.log(this.authData.facebook.displayName);
    }

    this.getAuthData = function() {
        return this.authData;
    }

    return {
        authenticateWithGoogle: this.authenticateWithGoogle,
        authenticateWithFacebook: this.authenticateWithFacebook,
        getAuthData: this.getAuthData            
    }
}

angular.module('starter.services').service('AppService', AppService);

dashboard.js

function DashCtrl($scope, AppService) {
    $scope.user = "";
    $scope.openBrowser = function() {
        AppService.authenticateWithFacebook();
        /*var authData = AppService.getAuthData();
        $scope.user = authData.facebook.displayName;
        console.log(authData);
        console.log($scope.user);*/
    }
}

angular.module("starter.controllers", []).controller('DashCtrl', DashCtrl);

During my implementation, I encountered the error "

this.authDataAvailable is not a function
" in AppService.js while calling this.authDataAvailable(); under this.authenticateWithFacebook function.

I would appreciate insights on an effective way or best practice to handle such scenarios.

Update

To resolve the issue, I found 2 helpful techniques with assistance from mJunaidSalaat:

  1. Implementing something like the following in my AppService.js:

    this.authenticateWithFacebook = function() {
        FirebaseService.authWithOAuthPopup("facebook")
        .then(function(data) {
            service.authData = data;
            console.log(this.authData);
            service.authDataAvailable();
            console.log(this.authData.facebook.displayName);
        }, function(err) {
            console.log(err)
        });
     }
    
  2. Using an identifier for this as its context changes inside any enclosure. Thus, I used service in this scenario.

Answer №1

In FirebaseService.js, the callback function is not properly handling the received data promise. You can try implementing the following:

this.authWithOAuthPopup = function(type) {
        var deferred = $q.defer();
        this.appRef = new Firebase("https://lola.firebaseio.com");
        this.appRef.authWithOAuthPopup(type, function(error, authData) {
            if (error) {
                this.authError = error;
                switch (error.code) {
                    case "INVALID_EMAIL":
                        console.log("The specified user account email is invalid.");
                        break;
                    case "INVALID_PASSWORD":
                        console.log("The specified user account password is incorrect.");
                        break;
                    case "INVALID_USER":
                        console.log("The specified user account does not exist.");
                        break;
                    default:
                        console.log("Error logging user in:", error);
                }
                deferred.resolve(this.authError);
            } else {
                this.authData = authData;
                console.log("Authenticated successfully with payload:", authData);
                deferred.resolve(this.authData);
            }
        });
        return deferred.promise; // This returns the promise rejected or resolved with the supplied data
    }

and in AppService.js, you can handle the promise like this:

this.authenticateWithFacebook = function() {
        var service = this;
        FirebaseService.authWithOAuthPopup("facebook")
          .then(function(data){
            this.authData = data;
            console.log(this.authData.facebook.displayName);
            service.authDataAvailable();
          },function(err){
              console.log(err);
          });
    }

I hope this solution helps.

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

Is there a way to switch the series of an apex chart from one component, even if the chart itself is located in a separate

Currently, I am working with Apexchart and facing a challenge with 2 components. The apex chart resides in the second component, and I aim to trigger a function in the first component to toggle or deselect certain series within the chart of the second comp ...

Error: a is missing in the Google Maps configuration

I'm looking to integrate Google Maps into my program, but I've encountered an error stating that 'a is null' when using a variable in the Google Maps API. Below is my current implementation: //Creates a new center location for the goog ...

Unlocking the potential: passing designated text values with Javascript

In my current React code, I am retrieving the value from cookies like this: initialTrafficSource: Cookies.get("initialTrafficSource") || null, Mapping for API const body = {Source: formValue.initialTrafficSource} Desired Output: utmcsr=(direct)|utmcmd=(n ...

ajax memory leakage

Encountering a gradual memory leak issue in Internet Explorer and Firefox while utilizing a mix of ASP.NET AJAX and jQuery. The situation mirrors the one portrayed on this post: Preventing AJAX memory leaks, but with jQuery and ASP.NET AJAX instead of prot ...

To remove the next parameter, the error handler in express.js fails to function as expected

Currently, I am in the process of learning about Express.js and utilized their generator to create a new application with: npm install express-generator -g && express myapp Upon inspecting the app.js file, I noticed the following code snippet: / ...

Error: The function was not passed as a valid function

Currently, I am in the process of creating a concise 'Engine' class to streamline interactions with Three.js. I have restructured the Render() method from the example into this Engine JS class, as shown below: const Engine = function () { cons ...

What is the best way to maintain a fixed header for a content div?

I recently developed a website using angularjs. <html> <head></head> <body ng-app="app1" ng-controller = "ctrl1"> <header></header> <div ng-view></div> <footer></footer> </body> </ht ...

How can you determine if a table cell's property of "disable" is set to true or false using jQuery?

Every time I add a new row by clicking the addNewRow button, I make sure to validate all input cells in that row. Then, after clicking the "CompletedBtn," the row becomes disabled. However, when I try to edit a specific row by clicking the editBtn, I wan ...

Sharing a shared object array between directives in AngularJS

I've been attempting to pass an array of objects from a parent directive to a child directive, but when I use console.log($scope.$eval(attrs.model)), it shows up as undefined. angular.module('tester').directive('gChart',gChart); ...

Plotting live-updating data with JQplot

Utilizing JQPlot, JavaScript, Asp.net 4.5, C# and MS Visual Studio 2012. Hello all! I'm facing an issue with the following code: script> $(document).ready(function () { var dataArray = []; <%foreach(Last12MonthsRegistered reg in dbreg ...

Tips on saving JSON response data into an array

After making an ajax request in jQuery, I received a response that is not in array format. {"ErrorCode":0,"SeriesSocialStats":{"8970471":{"faves":1,"friendFaves":0,"friendLikes":0,"likes":1,"myFaves":1,"myLikes":0,"seriesId":"8970471"}}} {"ErrorCode":0,"S ...

Is there a way to navigate to a link with CasperJS without having to specify the CSS selector?

<a href="pss.exe?TRANSACTION=CGI_JUMP&amp;SESSDATA=randomstuff&amp;SKIN=default&amp;LANG=en-US"> Update your password </a> <a href="psk.exe?TRANSACTION=CGI_JUMP&amp;SESSDATA=randomstuff&amp;SKIN=default&amp;LANG=en ...

What steps can I take to incorporate additional arguments into my function?

I am currently working with NodeJS, express, and passport. However, I believe this question is specifically related to JavaScript. Within my routes file, I have the following code: app.get( '/users', login_req, user.index); So, when a get requ ...

What is the significance of Fawn's statement, "Invalid Condition"?

Despite following the instructions and initiating Fawn as stated in the document, I'm still encountering an error message that says Invalid Condition. Can anyone help me identify what is causing this issue? Thank you to all the helpers. await new Fawn ...

Mobile devices consistently experiencing issues with JavaScript generated elements overlapping

I'm currently in the process of creating a quiz based on a tutorial I found at https://www.sitepoint.com/simple-javascript-quiz/. While I followed the tutorial closely and integrated Bootstrap, I am encountering an issue specifically with mobile devic ...

Submit information with Ajax in multipart/form format

Here is the HTML code I have: <form:form name="vcfForm" id="vcfForm" method="post" enctype="multipart/form-data" action="../acquaintance/readingContactsFromVcfFile"></form:form> <input type="file" name="vcfFile" id="vcfFile" form="vcfForm" ...

Fluid sifting and interactive webpage

I'm almost done with my website, but I'm facing a problem. There are 3 blocks of text on my page - 2 static and 1 dynamic. When I click a button, the page should change, which is working fine. However, when I added smooth scroll to the website, ...

Disabling a button in PHP when the records column is empty: A step-by-step guide

Is there a way to dynamically disable a button in a table if certain columns in the database are empty? I have two buttons, View and Cancel, displayed in an echo statement. The values are retrieved from the database and shown in a table. I would like the ...

Implementing a New Port Number on a ReactJs Local Server Every Time

As a newcomer to ReactJS, I recently encountered an issue while working on a project that puzzled me. Every time I shut down my local server and try to relaunch the app in the browser using npm start, it fails to restart on the same port. Instead, I have ...

Utilizing ng-repeat, filter, and the uib-popup-datepicker to refine and display specific data within a table column

I'm currently facing a common scenario in my Angular application where I need to filter items from an ng-repeat using an HTML5 input of type 'date' or Angular-UI-Bootstrap's 'uib-popup-datepicker'. Despite extensive research, ...