Patrick
Patrick

Reputation: 4298

How to use a promise from an jQuery ajax call in Angular

I am trying to use promise as follows...

 $q.when().then(function () {
    return $rootScope.$emit('resetView', false, 'default');
}).then(function (result) {
    $log.info('login id loaded');   //execute this one first
    checkUserlogin();
}).then(function (result) {
    $log.info('Layout loaded');     //execute this one only when 1st is success. If 1st is failed, dont execute this one.
    loadData();
}, function (error) {
    $log.error("Caught an error:", error);
    return $q.reject('New error');
});

As you can see, i have 2 functions to be executed. checkUserLogin() and loadData().

In checkUserLogin(), we check if user is allowed access. User ID is taken and passed to backend via ajax. Database is checked. If access is there, then loadData() should execute. If access is not there, loadData() should not execute.

Currently, this is wat is happening. checkUserLogin() is executed. User id is passed to backend via ajax. And directly loadData() gets executed. Now once page is loaded, ajax returns call and gets to know that user doesnot have access. He is redirected to access denied page.

I dont want this to take place. Page loading should only happen once it is confirmed that user has access. Any idea how to achieve this ?

EDIT (As per Paulpro's answer below)

$q.when().then(function () {
return $rootScope.$emit('resetView', false, 'default');

}).then(function (result) {
$log.info('checkuser loaded');   //execute this one first
return checkUserlogin();

}).then(function (result) {
$log.info('Layout loaded');     //execute this one only when 1st is success. If 1st is failed, dont execute this one.
return loadData();

}, function (error) {
$log.error("Caught an error:", error);
return $q.reject('New error');
});


var checkUserlogin = function() {
$log.info(' Inside Login check function executed');  
 var serviceURL_CheckUserExists = '/api//CheckUserExists';

    //ajax to check if user exists in database. give/ deny access based on user present in DB and if user is set as blockuser in db. 
    $.ajax({
        type: "GET",
        url: serviceURL_CheckUserExists,
    }).then(function (response) {
        if (response.Results.length == 1 && response.Results[0].BlockUser == false) {
            $rootScope.myLayout.eventHub.emit('getUserName', response.Results[0].User_ID.trim());

            });
        }
        else { $window.location.href = '../../../BlockUser.html'; }
}

as per the above edit- here is the steps which is currently getting executed. $log.info gives output as follows.

checkuser loaded
Layout loaded
Inside Login check function executed

In actual, these should be the steps.

checkuser loaded
Inside Login check function executed
Layout loaded

Upvotes: 1

Views: 782

Answers (3)

Victory
Victory

Reputation: 5890

Modify your check function to return a promise and throw if you arn't logged in and return user if you are.

var checkUserlogin = function() {
 $log.info(' Inside Login check function executed');  
 var serviceURL_CheckUserExists = '/api/CheckUserExists';

    //ajax to check if user exists in database. give/ deny access based on user present in DB and if user is set as blockuser in db. 
 return $.ajax({
        type: "GET",
        url: serviceURL_CheckUserExists,
 }).then(function (response) {
   if (response.Results.length == 1 && response.Results[0].BlockUser == false) {
     return response.Results[0].User_ID.trim();
   }
   else 
   { 
     return null; // could not login
   }
 });
}

At which point you can do

$q.when().then(function () {
    return $rootScope.$emit('resetView', false, 'default');
}).then(function (result) {
    $log.info('login id loaded');   //execute this one first
    return checkUserlogin();
}).then(function (result) {
    $log.info('Layout loaded');     // execute this when we know if we are logged in or not
   // not logged in
   if (result === null) {
      $window.location.href = '../../../BlockUser.html';
      return;
    }

    // we have a good user so emit
    $rootScope.myLayout.eventHub.emit('getUserName', result);
    // finally load data
    loadData();
}, function (error) { // redirect on blocked user
    $log.error("Caught an error:", error);
});

Upvotes: 1

Paul
Paul

Reputation: 141839

The functions you pass into then should return another Promise, otherwise the call to then will return a promise that resolves immediately (to the return value of the function, undefined in your case). You want to return promises that don't resolve until the ajax calls are finished. Assuming that checkUserLogin(); and loadData(); both return promises, you just need to add a couple of return statements:

$q.when().then(function () {
    return $rootScope.$emit('resetView', false, 'default');
}).then(function (result) {
    $log.info('login id loaded');   //execute this one first
    return checkUserlogin();
}).then(function (result) {
    $log.info('Layout loaded');     //execute this one only when 1st is success. If 1st is failed, dont execute this one.
    return loadData();
}, function (error) {
    $log.error("Caught an error:", error);
    return $q.reject('New error');
});

If they don't return promises, modify them so that they do (but avoid using the Promise constructor) and then the code above will work.

Upvotes: 2

Billy Moon
Billy Moon

Reputation: 58531

Assuming checkUserlogin returns a promise, try...

$q.when().then(function() {
    return $rootScope.$emit('resetView', false, 'default');
}).then(function(result) {
    $log.info('login id loaded'); //execute this one first
    checkUserlogin().then(function(result) {
        $log.info('Layout loaded'); //execute this one only when 1st is success. If 1st is failed, dont execute this one.
        loadData();
    }, function(error) {
        $log.error("Caught an error:", error);
        return $q.reject('New error');
    });
});

Upvotes: 1

Related Questions