joropicha joropicha - 1 month ago 6
AngularJS Question

Can't get $q promise in Angular factory to work correctly

The factory doesn't return anything, it just writes to a json file. I can't figure out how to use $q in this case to be sure it's done writing.

This is causing me problems in a controller, because even if I use a callback, the code does not execute in the correct order..

angular.module('jsonWrite', [])
.factory('JsonWrite', function($q) {
var nw = require('nw.gui');
var fs = require('fs');
var path = require('path');

var file = "myjsonfile.json";
var filePath = path.join(nw.App.dataPath, file);

var write = {};

write.writeJson = function(x){
var deferred = $q.defer();
fs.access(filePath, fs.F_OK, function(err) {
if (!err) {
fs.readFile(filePath, 'utf8', function(err, data) {
var myObj = JSON.parse(data);
myObj = x;
fs.writeFileSync(filePath, JSON.stringify(myObj));
});
}

else {
fs.open(filePath, "w", function(err, data) {
var myObj = {};
myObj = x;
fs.writeFileSync(filePath, JSON.stringify(myObj));
});
};
$q.resolve();
});
return deferred.promise;
};

return(write);

});


This is an example of the controller function, even if there's a callback, JsonWrite is not done writing before StateChanger.changeState executes. This causes heaps of trouble. If I put a $timeout on StateChanger, everything works fine - it executes after JsonWrite is done writing.

$scope.change = function(x){

function write(callback){
JsonWrite.writeJson(x);
callback();
};


function change(){
writemystuff(function(){
StateChanger.changeState(); // <- $timeout here and it works
})
};

change();

};


If anyone can give me an idea on what can be done, I'd be very grateful

Answer

Your factory looks fine. But you need to use your promise - this means you need you use a ".then()" syntax:

write.writeJson().then(function() {StateChanger.changeState()});

Have a look at these examples: https://docs.angularjs.org/api/ng/service/$q

function asyncGreet(name) {
  var deferred = $q.defer();

  setTimeout(function() {
    deferred.notify('About to greet ' + name + '.');

    if (okToGreet(name)) {
      deferred.resolve('Hello, ' + name + '!');
    } else {
      deferred.reject('Greeting ' + name + ' is not allowed.');
    }
  }, 1000);

  return deferred.promise;
}

var promise = asyncGreet('Robin Hood');
promise.then(function(greeting) {
  alert('Success: ' + greeting);
}, function(reason) {
  alert('Failed: ' + reason);
}, function(update) {
  alert('Got notification: ' + update);
});