Amir Lavi
Amir Lavi

Reputation: 37

Nodejs and express routing, how to handle client side promises

I'm trying to do a single routing back and forth to mongodb, but it seems that on the client side I can't retrieve the data out of the promise received from $resource. On the HTML page there's a button who has ng-click to this following function:

$scope.getToken = function() {
    console.log('$scope.getToken()');
    authenticationService.getToken($scope.data.email).then(function(result) {
        $scope.data.token = result;
    });
}

The result received is:

object "m", with fields - 0: "j", 1: "6", 2: "o", 3: "p", 4: "E", 5: "7", 6: "X", 7: "t", $promise: d, $resolved: true, proto: Object

As you can see I receive the token generated, the database seems to work fine and the function invoking as well.

The service on the client side that receive the answer has a function:

    function getToken(userEmail) {
    var deferred = $q.defer();
    $resource(baseUrl + '/getToken').save({
        email : userEmail
    }, function(result, error) {
        if(result) {
            deferred.resolve(result);
        }
        else {
            deferred.reject(error);
        }
    });
    return deferred.promise;
}

The function on the server side that sent this:

var router = require('express').Router();
var authenticator = require('../utils/authUtils');
router.post('/getToken', function(request, response) {
authenticator.getToken(
    function(error, result) {
        if(error) {
            //handle error
        }
        else if(result) {
            response.json(result);
        }
    }
);

And in authUtils.js:

var mongoUtils = require('./mongoUtils');
getToken : function(callback) {
    var genToken = randToken.generate(8);
    mongoUtils.query(COLLECTIONS.TOKENS, {'token': { $eq: genToken } },
        function(error, result) {
            if((result && result.length) || error) {
                //handle error or duplicates
            }
            else if(result) {
                callback(null, genToken);
            }
        }
    );
}

And in mongoUtils:

query : function(collectionName, query, callback) {
    _db.collection(collectionName).find(query).toArray(function (error, result) {
        console.log('Utils.query');
        if(error) {
            //handle error
        }
        else {
            callback(error, result);
        }
    });
}

Why the server side sends the answer inside an object along with the promise, and how should I handle it?

Upvotes: 1

Views: 595

Answers (2)

Wcan
Wcan

Reputation: 878

So you have 3 parts in your questions, why an object, why promise and how to handle it.

1: Why Inside an object ?

According to Angular official $resource page $resource When you are using $resourceThe returned resource is always object, also in your API (Server side) you are sending the response back as a json object so you will obviously get object.

else if(result)
{
    response.json(result);
}

2: Why Promise ?

$resource and $http both return a promise, REST is a subset of HTTP. This means everything that can be done via REST can be done via HTTP but not everything that can be done via HTTP can be done via REST. That is why $resource uses $http internally. $resource is built on top of $http. so $promise is for sure. for reference Why Promise

3: How to Handle it

I'm not exactly sure what do you mean by "How to Handle It" since you already have the object I would assume you meant to separate the actual generated token data object and leave everything else, if that's the case than you can simply assign the data within the result object the your $scope.

what you are doing is assigning the entire object to $scope which has all other objects

 $scope.data.token = result;

what you can do is simply assign the generated token to $scope.data.token for instance:

$scope.data.token = result.genToken;

Hope this will answer the question.

Upvotes: 0

jmunsch
jmunsch

Reputation: 24109

The reason its being returned as an indexed object is because of toArray in:

 _db.collection(collectionName).find(query).toArray(function... 

A possible solution would be to not use toArray on a string or to call slice before sending back the result:

response.status(200).json({token: Array.prototype.slice.call(result)})

Another possibility as I may not understand your question completely is try:

authenticationService.getToken($scope.data.email).$promise.then(...)

If it is a ngResource I have accessed the then via $promise, just a thought.

Upvotes: 1

Related Questions