j-terranova
j-terranova

Reputation: 659

Angular callback or promise to trap return vale

I am racking my brain trying to get this to work correctly. I have tried callbacks and promises and am open to both. I modeled my code using the Mean Stack as laid out by Joe Eames in a Pluralsight class. I am still learning so please excuse my terminology if incorrect but here is how this works with code as illustrated below.

My interface calls flQuestionCrudCtrl.createQuestion that calls flQuestionCrud.createNewQuestion that calls flQuestion.Create. flQuestion.Create makes an http post request to a server that writes to a mongodb collection. Everything seems to work fine, data is written to the database and I can see the return value in flQuestionCrud per console logs. When I try to read the “data” return parameter in flQuestionCrudCtrl I get, “Error: data is undefined”. I have tried every combination of callback and promise but cannot get it to work. Can you see what I am doing wrong?

  angular.module('app').controller( 'flQuestionCrudCtrl',function(flConstructDataService, flQuestionDataService, flQuestionCrud, flCachedReferenceData,flCachedQuestions, flAnswer, $scope, $location, $q, flIdentity, flNotifier,$timeout, $state) {


$scope.createQuestion = function() {

function doWorkAsync() {
    return $timeout(flQuestionCrud.createNewQuestion(currentQuestionData), 10);
}

doWorkAsync()
    .then(function(data) {
        console.log("flQuestionCrudCtrl - Success " + data);
        console.log("flQuestionCrudCtrl - Success Statement " + data.statement);
        console.log("flQuestionCrudCtrl - Success Question id " + data._id);
        currentQuestionData._id = data._id;
        flQuestionDataService.setNewQuestionId(data._id);
        console.log("flQuestionCrudCtrl - currentQuestionData._id " + currentQuestionData._id);
        console.log("flQuestionCrudCtrl - flQuestionDataService.getNewQuestionId() " + flQuestionDataService.getNewQuestionId());
        $state.go('questionUpdate');
    })
    .catch(function(err) {
        console.log("flQuestionCrudCtrl - Error " + err);
        $state.go('questionCreate');
    })
    .finally();
};

}


angular.module('app').factory('flQuestionCrud',function($http, $q, $state, $timeout, flQuestion ){
    return {
        createNewQuestion: function(newQuestionData) {
            console.log("Before - flQuestion.create");

        function createQuestionDataAsync(questionData) {
            console.log("flQuestionCrud - Before Call to create ")
            var returnData;
            flQuestion.create(questionData, function(data) {
                console.log("flQuestionCrud - After Call to create ")
                if (!data){
                    return Error("Error Creating Data");
                    //return null;
                }
                else {
                    console.log("flQuestionCrud - Try Section - Success " + data);
                    console.log("flQuestionCrud - Try Section - Success Statement " + data.statement);
                    console.log("flQuestionCrud - Try Section - Success Question id " + data._id);
                }
                return data;
            });
        }

        createQuestionDataAsync(newQuestionData); 
    },

Upvotes: 0

Views: 158

Answers (1)

Alexander Kravets
Alexander Kravets

Reputation: 4395

Your flQuestionCrud.createNewQuestion() method should return the promise resolved with data:

angular.module('app')
    .factory('flQuestionCrud', function($http, $q, $state, $timeout, flQuestion ){
        return {
            createNewQuestion: function(newQuestionData) {
                var deferred = $q.defer();

                flQuestion.create(questionData, function(data) {
                    if (data){
                        // whatever we resolve the promise with will be passed 
                        // to the `then` handler in the controller
                        deferred.resolve(data);
                    }
                    else {
                        deferred.reject("Error Creating Data");
                    }
                });

                return deferred.promise;
            }
            // ...
        }
    });

Note, we're explicitly creating the promise and resolve or reject it depending on what flQuestion.create() returns.

This way you'll be able to access the data in your controller the way you do it:

flQuestionCrud.createNewQuestion(currentQuestionData)
    .then(function(data) {
        // work with data here
    });

or

doWorkAsync()
    .then(function(data) {
        // work with data here
    });

Upvotes: 2

Related Questions