BreezeJS - Chaining Queries - javascript

Say we have a Customer Object, that has a "Foo" collection. I'd like my "getCustomer" function to add all Foos it does not have already, and then return itself, as a promise...
So I'd like a promise to: Get a Customer, then add all missing Foos to this Customer, so that when the promise is resolved, the customer has all missing foos.
Example:
// dataservice.js
// returns Q.Promise<breeze.QueryResult>
function getCustomer(custId) {
var query = breeze.EntityQuery().from("Customers").where("CustomerId", "==", custId);
return this.em.executeQuery(query);
}
// returns Q.Promise<breeze.QueryResult>
function getFoosNotOnCustomer(customer) {
var query = breeze.EntityQuery().from("Foo").where("CustomerId", "!=", customer.Id());
return this.em.executeQuery(query);
}
I am struggling with how to "chain" these together properly, what do do if no customer is found, etc. How can I modify "getCustomer" to do this? I am basically trying to user breeze synchronously. Here is my attempt, but it turns into ugly nested code in a hurry.
// want to return Q.Promise<Customer> that has Foos loaded
// I think this is actually returning something like Q.Promise<Q.Promise<Customer>>
function getCustomer(custId) {
var query = breeze.EntityQuery().from("Customers")
.where("CustomerId", "==", custId);
return this.em.executeQuery(query) // return here?
.then(function(data) {
// what about conditionals?
if(data.results.length == 1) {
getFoosNotOnCustomer(data.results[0]).
then(function (foosArray) {
$.each(foosArray, function(i,el) {
// push foos onto customer instance
}
return custWithFoos; // return here?
}
// return something?
}
}
}
Here's what I ended up doing:
function getCustomer(custId) {
var query = breeze.EntityQuery().from("Customers").where("CustomerId", "==", custId);
return manager.executeQuery(query) // return here?
.then(addFoos)
.then(doSomethingElse);
}
function addFoos(data) {
var myDefer = Q.Defer();
if (data && data.result.length == 1) {
var customer = data.results[0];
var query = // get FOOS Customer doesn't have;
manager.executeQuery(query).then(function (fooData) {
$.each(fooData.results function (i, el) {
customer.Foos.push(el);
});
myDefer.reslove(customer);
});
} else {
myDefer.resolve(undefined);
}
return myDefer.promise;
}
function doSomethingElse(customer) {
var myDefer = Q.Defer();
customer.SomePropert("test");
return myDefer.resovlve(customer);
}
// ----- MVVM
var custPromise = getCustomer(1).then(function (customer) {
// do something
});

I will take your example on face value despite my inability to understand the semantics ... in particular my inability to understand why getting all Foos not belonging to the customer is going to be helpful.
I'll just focus on "chaining" and I'll assume you want the caller to take possession of the selected customer when you're done.
Sequential chaining
In this example, we wait for the customer before getting the Foos
function getCustomer(custId) {
var cust;
var em = this.em;
var query = breeze.EntityQuery().from("Customers")
.where("CustomerId", "==", custId);
// On success calls `gotCustomer` which itself returns a promise
return em.executeQuery(query)
.then(gotCustomer)
.fail(handleFail); // you should handleFail
// Called after retrieving the customer.
// returns a new promise that the original caller will wait for.
// Defined as a nested success function
// so it can have access to the captured `cust` variable
function gotCustomer(data) {
cust = data.results[0];
if (!cust) {
return null; // no customer with that id; bail out now
}
// got a customer so look for non-customer foos
// returning another promise so caller will wait
return breeze.EntityQuery().from("Foos")
.where("CustomerId", "!=", custId)
.using(em).execute()
.then(gotFoos);
}
// Now you have both the customer and the other Foos;
// bring them together and return the customer.
function gotFoos(data) {
var foos = data.results;
// assume `notMyFoos` is an unmapped property that
// should hold every Foo that doesn't belong to this Customer
foos.forEach(function(f) { cust.notMyFoos.push(f); }
return cust; // return the customer to the caller after Foos arrive.
}
}
Parallel async queries
In your scenario you really don't have to wait for the customer query before getting the foos. You know the selection criterion for both the customer and the foos from the start. Assuming you think that there is a high probability that the customer query will return a customer, you might fire off both queries in parallel and then mash up the data when both queries complete. Consider the Q.all for this.
function getCustomer(custId) {
var em = this.em;
var custPromise = breeze.EntityQuery().from("Customers")
.where("CustomerId", "==", custId)
.using(em).execute();
var fooPromise = breeze.EntityQuery().from("Foos")
.where("CustomerId", "!=", custId)
.using(em).execute();
Q.all([custPromise, fooPromise])
.then(success)
.fail(handleFail); // you should handleFail
// Now you have both the customer and the "other" Foos;
// bring them together and return the customer.
// `data` is an array of the results from each promise in the order requested.
function success(data) {
var cust = data[0].results[0];
if (!cust) return null;
var foos = data[1].results;
// assume `notMyFoos` is an unmapped property that
// should hold every Foo that doesn't belong to this Customer
foos.forEach(function(f) { cust.notMyFoos.push(f); }
return cust; // return the customer to the caller after Foos arrive.
}
}
Notice that I don't have to do so much null checking in the success paths. I'm guaranteed to have data.results when the success callback is called. I do have to account for the possibility that there is no Customer with custId.

Related

getting object Parse from a loop

In a Parse server function, it's getting Matches and profiles.
From a query to get matches another function is called to get Profiles by id but the result is :
{"_resolved":false,"_rejected":false,"_reso resolvedCallbacks":[],"_rejectedCallbacks":[]}
Main Query :
mainQuery.find().then(function(matches) {
_.each(matches, function(match) {
// Clear the current users profile, no need to return that over the network, and clean the Profile
if(match.get('uid1') === user.id) {
match.set('profile2', _processProfile(match.get('profile2')))
match.unset('profile1')
}
else if (match.get('uid2') === user.id) {
var profileMatch = _getProfile(match.get('profile1').id);
alert(">>>"+JSON.stringify(profileMatch));
match.set('profile1', _processProfile(match.get('profile1')))
match.unset('profile2')
}
})
the function to get Profile info:
function _getProfile(id){
var promise = new Parse.Promise();
Parse.Cloud.useMasterKey();
var queryProfile = new Parse.Query(Profile);
return queryProfile.equalTo("objectId",id).find()
.then(function(result){
if(result){
promise.resolve(result);
alert("!!!!"+result);
}
else {
console.log("Profile ID: " + id + " was not found");
promise.resolve(null);
}
},
function(error){
promise.reject(error)
});
return promise;
}
Just found this a little late. You've probably moved on, but for future readers: the key to solving something like this is to use promises as returns from small, logical asynch (or sometimes asynch, as in your case) operations.
The whole _getProfile function can be restated as:
function _getProfile(id){
Parse.Cloud.useMasterKey();
var queryProfile = new Parse.Query(Profile);
return queryProfile.get(id);
}
Since it returns a promise, though, you cannot call it like this:
var myProfileObject = _getProfile("abc123");
// use result here
Instead, call it like this:
_getProfile("abc123").then(function(myProfileObject) { // use result here });
Knowing that, we need to rework the loop that calls this function. The key idea is that, since the loop sometimes produces promises, we'll need to let those promises resolve at the end.
// return a promise to change all of the passed matches' profile attributes
function updateMatchesProfiles(matches) {
// setup mainQuery
mainQuery.find().then(function(matches) {
var promises = _.map(matches, function(match) {
// Clear the current users profile, no need to return that over the network, and clean the Profile
if(match.get('uid1') === user.id) {
match.set('profile2', _processProfile(match.get('profile2'))); // assuming _processProfile is a synchronous function!!
match.unset('profile1');
return match;
} else if (match.get('uid2') === user.id) {
var profileId = match.get('profile1').id;
return _getProfile(profileId).then(function(profileMatch) {
alert(">>>"+JSON.stringify(profileMatch));
match.set('profile1', _processProfile(match.get('profile1')))
match.unset('profile2');
return match;
});
}
});
// return a promise that is fulfilled when all of the loop promises have been
return Parse.Promise.when(promises);
}

Understanding JavaScript promises in Parse

I am developing an app in Parse and I'm trying to understand promises. I'm not finding very many working examples other than the very simple ones here: https://parse.com/docs/js/guide.
I'm querying the _User table. Then I loop through the users in an _.each loop. I'm running 2 cloud functions inside the loop for each iteration. At what point do I create the promise? Do I create one for each cloud function success within the loop? Or do I push each success return value onto an array and make that the promise value outside of the loop? I've tried both but I can't figure out the correct syntax to do either, it seems.
I'll break it down in pseudo-code because that may be easier than actual code:
var query = new Parse.Query(Parse.User);
query.find().then(function(users){
loop through each user in an _.each loop and run a cloud function for each that returns a number.
If the number > 0, then I push their username onto array1.
Then I run a 2nd cloud function on the user (still within the _.each loop) that returns a number.
If the number > 0, then I push their username onto array2.
}).then(function(promisesArray){
// I would like "promisesArray" to either be the 2 arrays created in the preceding section, or a concatenation of them.
// Ultimately, I need a list of usernames here. Specifically, the users who had positive number values from the cloud functions in the preceding section
concatenate the 2 arrays, if they're not already concatenated
remove duplicates
send push notifications to the users in the array
});
Questions:
- At what point do I create & return promises & what syntax should I use for that?
- Should .then(function(promisesArray){ be .when(function(promisesArray){ (when instead of then)?
Thank you both for your ideas! This is what ultimately worked:
var query = new Parse.Query(Parse.User);
query.find().then(function(users){
var allPromises = [];
var promise1, promise2;
_.each(users, function(user){
if(user.get("myvalue") != "undefined" && user.get("myvalue") != ""){
promise1 = Parse.Cloud.run("getBatch1", {param1: param1value, param2: param2value})
.then(function(numResult){
if(Number(numResult) > 0){
return Parse.Promise.as(user.getUsername());
}
});
}
allPromises.push(promise1);
if(user.get("anothervalue")==true){
promise2 = Parse.Cloud.run("getBatch2", {param1: param1value, param2: param2value})
.then(function(numResult2){
if(Number(numResult2) > 0){
return Parse.Promise.as(user.getUsername());
}
});
}
allPromises.push(promise2);
});
// Return when all promises have succeeded.
return Parse.Promise.when(allPromises);
}).then(function(){
var allPushes = [];
_.each(arguments, function(pushUser){
// Only add the user to the push array if it's a valid user & not already there.
if(pushUser != null && allPushes.indexOf(pushUser) === -1){
allPushes.push(pushUser);
}
});
// Send pushes to users who got new leads.
if(allPushes.length > 0){
Parse.Push.send({
channels: allPushes,
data: {
alert: "You have new leads."
}
}, {
success: function () {
response.success("Leads updated and push notifications sent.");
},
error: function (error) {
console.log(error);
console.error(error);
response.error(error.message);
}
});
}
response.success(JSON.stringify(allPushes));
}, // If the query was not successful, log the error
function(error){
console.log(error);
console.error(error);
response.error(error.message);
});
I'm not familiar with Parse API but I'd do it this way. Of course, I can't test my code so tell me if it works or not:
var query = new Parse.Query(Parse.User);
query.find()
.then(function(users) {
var promises = [];
users.forEach(function(user) {
// the first API call return a promise so let's store it
var promise = cloudFn1(user)
.then(function(result) {
if (result > 0) {
// just a way to say 'ok, the promise is resolved, here's the user name'
return Parse.Promise.as(user.name);
} else {
// return another promise for that second API call
return cloudFn2(user).then(function(res) {
if (result > 0) {
return Parse.Promise.as(user.name);
}
});
}
});
// store this promise for this user
promises.push(promise);
});
// return a promise that will be resolved when all promises for all users are resolved
return Parse.Promise.when(promises);
}).then(function(myUsers) {
// remove duplicates is easy with _
myUsers = _.uniq(myUsers);
// do your push
myUsers.forEach( function(user) {
});
});
First, you need to understand what Promises are. From what I understand of what you're trying to do it should look something like this:
//constructs the Parse Object
var query = new Parse.Query(Parse.User);
//find method returns a Promise
var res = query.find()
//good names will be a Promise of an array of usernames
//whose value is above 0
var goodNames = res
.then(function(data) {
//assumes the find method returns an array of
//objects, one of the properties is username
//we will map over it to create an Array of promises
//with the eventual results of calling the AJAX fn
var numberPromises = data.map(function(obj) {
//wrap the call to the cloud function in a new
//promise
return new Promise(resolve, reject) {
someCloudFn(obj.username, function(err) {
if (err) {
reject(err);
} else {
resolve(num);
}
});
}
};
//Promise.all will take the array of promises of numbers
//and return a promise of an array of results
return [data, Promise.all(numberPromises)];
})
.then(function(arr) {
//we only get here when all of the Promises from the
//cloud function resolve
var data = arr[0];
var numbers = arr[1];
return data
.filter(function(obj, i) {
//filter out the objects whose username number
//is zero or less
return numbers[i] > 0;
})
.map(function(obj) {
//get the username out of the query result obj
return obj.username;
});
})
.catch(function(err) {
console.log(JSON.stringify(err));
});
Now whenever you need to use the list of usernames whose number isn't zero you can call the then method of goodNames and get the result:
goodNames.then(function(listOfNames) {
//do something with the names
});

Exiting Final Promise Scope from Within a Generator Function

I'm having trouble trying to return promise results as a yield back to the original caller.
store.js
module.exports = {
find: function *(storeRequest){
if(!_gateway){
_gateway = realGateway;
}
storeResponse.http.statusCode = 200;
var stores = _gateway.find(storeRequest.id).next().value; // I want to be able to get the stores array back here ultimately by calling next() like I am trying to do here
console.log(stores[0]);
//yield storeResponse;
}
};
storeGateway.js
module.exports = {
find: function *(id){
var stores = [];
var entity;
database.find.then(function(foundStores){
entity = testUtil.createStore(foundStores[0].id, foundStores[0].name);
console.log("ENTITY:");
console.log(entity);
stores.push(entity);
console.log("STORES[0]:");
console.log(stores[0]);
// I am getting the results here successfully so far when I console.log(stores[0])! But now I want to return stores now from here and yield the array so it propogates up to the caller of storeGateway's find()
// yield entity; --- this doesn't work because I think I'm in the promise then scope
}
);
//yield entity; -- and this definitely won't work because it's not in the promise callback (then)
}
};
database.js
var co = require('co');
var pg = require('co-pg')(require('pg'));
var config = require('./postgreSQL-config');
var database = module.exports = {};
var _id;
var _foundStores;
database.find = co(function* poolExample(id) {
var query = "Select id, name from stores";
try {
var connectionResults = yield pg.connectPromise(config.postgres);
var client = connectionResults[0];
var done = connectionResults[1];
var result = yield client.queryPromise(query);
done();
console.log("PRINTING ROWS:");
console.log(result.rows[0]);
_foundStores = yield result.rows;
} catch(ex) {
console.error(ex.toString());
}
console.log("RESULTS!:");
console.log(_foundStores);
return _foundStores;
});
I'm getting data printed on every console.log you see above. I just don't know how to return the stores from the storeGateway's find() method since it's receiving the stores array in the promise result (in the .then()) and I need to be able to yield that back upstream.
(see my comment in code, I'm trying to return the found stores in the promise's then back upstream from my store.js's find generator function).
The point of using generators and co is that you can yield promises to the coroutine runner and get their results back, so that you don't have to use then.
Start by making find a method in your database.js:
database.find = co.wrap(function* poolExample(id) {
// ^^^^^
…
});
Then in storeGateway.js you should be doing
module.exports = {
find: function*(id) {
var foundStores = yield database.find(id);
var entity = testUtil.createStore(foundStores[0].id, foundStores[0].name);
console.log("ENTITY:", entity);
var stores = [entity];
console.log("STORES[0]:", stores[0]);
return stores;
}
};
(maybe wrap the generator function in co.wrap(…)).
Then in store.js you can do
module.exports = {
find: co.wrap(function*(storeRequest) {
if (!_gateway) _gateway = realGateway;
storeResponse.http.statusCode = 200;
var stores = yield* _gateway.find(storeRequest.id);
// or yield _gateway.find(storeRequest.id); if you did wrap it and it
// returns a promise, not a generator
console.log(stores[0]);
return stores;
})
};
There are two ways to do this. You either receive a call back parameter into your function and call it when the promise is resolved (inside your then function) or better, return the result of then. then() itself returns a promise and whatever you return from with in the function are available to the subsequent functions chained to the promise, so if you do this
return database.find.then(function(foundStores){
entity = testUtil.createStore(foundStores[0].id, foundStores[0].name);
console.log("ENTITY:");
console.log(entity);
stores.push(entity);
console.log("STORES[0]:");
console.log(stores[0]);
return stores[0];
}
then you could do gateway.find().then(function(stores){}) and stores would be what you returned i.e. stores[0].

How to handle asynchronous callbacks in Node.js module?

This is my first stab at attempting to put together a node module and I am still trying to wrap my head around how to structure the asynchronous callbacks. This is a case in point. Right now I am trying to use featureService.getCount() and getting nothing in response. Using breakpoints, I know featureService.getUniqueIds() is working.
Since a callback is in there, I am assuming the reason why I am not getting a length back is the callback in getCount has not responded yet. After looking at this for most of the afternoon and not really coming up with a very good solution other than a recursive loop checking for the value to be populated with a timeout, I am asking for advice how to better structure my code to accomplish the task at hand.
I have read a bit about promises. Is this an applicable instance or even a viable solution? I really have no clue how to implement promises, but it makes logical sense in such an instance.
Obviously I am lost here. Thank you for any help you can offer.
var Client = require('node-rest-client').Client;
var client = new Client();
var featureService = function(endpoint){
var uniqueIds;
var count;
// get list of unique id's
this.getUniqueIds = function(){
if (!uniqueIds) {
var options = {
parameters: {
f: 'json',
where: "OBJECTID LIKE '%'",
returnIdsOnly: 'true'
}
};
client.get(endpoint + '/query', options, function(data, res){
var dataObject = JSON.parse(data);
var uniqueIds = dataObject.objectIds;
return uniqueIds;
});
} else {
return uniqueIds;
}
};
// get feature count
this.getCount = function(){
// get uniqueIds
uniqueIds = this.getUniqueIds();
// get length of uniqueIds
count = uniqueIds.length;
};
// get list of unique attribute values in a single field for typeahead
this.getTypeaheadJson = function(field){};
// find features in a field with a specific value
this.find = function(field, value){};
};
var endpoint = 'http://services.arcgis.com/SgB3dZDkkUxpEHxu/arcgis/rest/services/aw_accesses_20140712b/FeatureServer/1';
var afs = new featureService(endpoint);
console.log(afs.getCount());
exports.featureService = featureService;
Now, after working it over some more and using request as in the bluebird documentation (I could not get the above module to work), I have this working, but cannot figure out how to get the calculated value to work with, the number of iterations.
var Promise = require("bluebird"),
request = Promise.promisifyAll(require("request"));
var FeatureService = function(){
// get count from rest endpoint
var getCount = function(){
var optionsCount = {
url: endpoint + '/query',
qs: {
f: 'json',
where: "OBJECTID LIKE '%'",
returnCountOnly: 'true'
}
};
return request.getAsync(optionsCount)
.get(1)
.then(JSON.parse)
.get('count');
};
// get max record count for each call to rest endpoint
var getMaxRecordCount = function(){
var optionsCount = {
url: endpoint,
qs: {
f: 'json'
}
};
return request.getAsync(optionsCount)
.get(1)
.then(JSON.parse)
.get('maxRecordCount');
};
// divide the total record count by the number of records returned per query to get the number of query iterations
this.getQueryIterations = function(){
getCount().then(function(count){
getMaxRecordCount().then(function(maxCount){
return Math.ceil(count/maxCount);
});
});
};
};
// url to test against
var endpoint = 'http://services.arcgis.com/SgB3dZDkkUxpEHxu/arcgis/rest/services/aw_accesses_20140712b/FeatureServer/1';
// create new feature service object instance
afs = new FeatureService();
// This seems like it should work, but only returns undefined
console.log(afs.getQueryIterations());
// this throws an error telling me "TypeError: Cannot call method 'then' of undefined"
//afs.getQueryIterations().then(function(iterCount){
// console.log(iterCount);
//});
Yes, use promises! They're a powerful tool, made for exactly this purpose, and with a decent library they're easy to use. In your case:
var Promise = require('bluebird'); // for example, the Bluebird libary
var Client = Promise.promisifyAll(require('node-rest-client').Client);
var client = new Client();
function FeatureService(endpoint) {
var uniqueIds;
var count;
// get list of unique id's
this.getUniqueIds = function(){
if (!uniqueIds) { // by caching the promise itself, you won't do multiple requests
// even if the method is called again before the first returns
uniqueIds = client.getAsync(endpoint + '/query', {
parameters: {
f: 'json',
where: "OBJECTID LIKE '%'",
returnIdsOnly: 'true'
}
})
.then(JSON.parse)
.get("objectIds");
}
return uniqueIds;
};
// get feature count
this.getCount = function(){
if (!count)
count = this.getUniqueIds() // returns a promise now!
.get("length");
return count; // return a promise for the length
};
// get list of unique attribute values in a single field for typeahead
this.getTypeaheadJson = function(field){};
// find features in a field with a specific value
this.find = function(field, value){};
};
var endpoint = 'http://services.arcgis.com/SgB3dZDkkUxpEHxu/arcgis/rest/services/aw_accesses_20140712b/FeatureServer/1';
var afs = new FeatureService(endpoint);
afs.getCount().then(function(count) {
console.log(count);
}); // you will need to use a callback to do something with async results (always!)
exports.FeatureService = FeatureService;
Here, using Bluebird's Promise.promisifyAll, you can just use .getAsync() instead of .get(), and will get a promise for the result.
// divide the total record count by the number of records returned per query to get the number of query iterations
this.getQueryIterations = function(){
getCount().then(function(count){
getMaxRecordCount().then(function(maxCount){
return Math.ceil(count/maxCount);
});
});
};
That's the right idea! Only you always want to return something from .then handlers, so that the promise returned by the .then() call will resolve with that value.
// divide the total record count by the number of records returned per query to get the number of query iterations
this.getQueryIterations = function(){
return getCount().then(function(count){
// ^^^^^^ return the promise from the `getQueryIterations` method
return getMaxRecordCount().then(function(maxCount){
// ^^^^^^ return the promise for the iteration number
return Math.ceil(count/maxCount);
});
});
};
Now, you get back a promise for the innermost result, and this will work now:
afs.getQueryIterations().then(function(iterCount){
console.log(iterCount);
});

Angularjs load resources on after the other using promise

Inside a service, I would like to load a resource using $http. Once loaded resource, I want to store it in a variable. Then, I need to load a child resource and store it too. I know that the promise is designed for this kind of work, but there seems to be so much how to use it I get a little confusion. Here is my code:
var project = {};
var todo = {};
function init(){
var idProject = 21;
var idTodo = 6;
// If idProject is specified
if ( idProject != null ) {
// First, load project data
var promise = WorkspaceManager.getProject($rootScope.workspace, idProject);
// Then save project data
promise.then(function(response){
project = response.data;
return project;
});
if ( idTodo != null ) {
// Then load todo data
promise.then(function(project){
return ProjectManager.getTodo(project, idTodo);
});
// Then save todo data
promise.then(function(response){
todo = response.data;
return todo;
});
}
}
console.log(project); // returns {}
}
init()
Thanks in advance !
If I understand correctly, this is trickier than it appears at first glance. You appear to need a function that chains two asynchronous processes and returns a promise of a composite value comprising data acquired by the first and the second processes.
At least two approaches are available :
Easy but inelegant: In each asynchronous process, accumulate the required values as properties of an outer object.
Elegant but awkward: From each asynchronous process, accumulate the required values as properties of an object, a promise of which is returned.
The code below adopts the first approach :
function init() {
var idProject = 21;
var idTodo = 6;
var projectObj = {};//This object acts as a "bank" for asynchrounously acquired data.
if ( idProject != null ) {
return WorkspaceManager.getProject($rootScope.workspace, idProject).then(function(response) {
projectObj.project = response.data;//put `response.data` in the bank as .project.
if( idTodo != null ) {
return ProjectManager.getTodo(response.data, idTodo);
}
}).then(function(toDo) {
projectObj.toDo = toDo;//put `toDo` in the bank as .toDo .
return projectObj;
});
}
}
init().then(function(projectObj) {
console.log(projectObj.project);
console.log(projectObj.toDo);
});
Or (still the first approach) with error handlers :
function init() {
var idProject = 21;
var idTodo = 6;
var projectObj = {};//This object acts as a "bank" for asynchrounously acquired data.
if ( idProject != null ) {
return WorkspaceManager.getProject($rootScope.workspace, idProject).then(function(response) {
projectObj.project = response.data;//put `response.data` in the bank as .project.
if( idTodo != null ) {
return ProjectManager.getTodo(response.data, idTodo);
}
else {
$q.defer().reject('idTodo invalid');
}
}).then(function(toDo) {
projectObj.toDo = toDo;//put `toDo` in the bank as .toDo .
return projectObj;
});
}
else {
return $q.defer().reject('idProject invalid');
}
}
init().then(function(projectObj) {
console.log(projectObj.project);
console.log(projectObj.toDo);
}, function(errorMessage) {
console.log(errorMessage);
});
untested
The way you doing, you're creating "brothers" promise derived from the first promise. All the promises are going to be resolved as soon as WorkspaceManager.getProject promise has been resolved. What I believe you want is to chain them all, in way that when first promise gets resolved, yo asks for Todo data, when you got it, you asks to save it. If this is the case, you shall grab the derived promise from each promise.
// Then save project data
promise = promise.then(function(response){
project = response.data;
return project;
});
// Then load todo data
promise = promise.then(function(project){
return ProjectManager.getTodo(project, idTodo);
});
// Then save todo data
promise.then(function(response){
todo = response.data;
return todo;
});
Trying to illustrate a bit more, the first approach is like:
var mainPromise = ...;
mainPromise.then(function loadTodo(mainPromiseReturn){});
mainPromise.then(function saveTodo(mainPromiseReturn){});
The loadTodo and saveTodo are pararell, they're not chained to each other. They both receive the same data.
The approach I suggest is like:
var mainPromise = ...;
mainPromise
.then(function loadTodo(mainPromiseReturn){})
.then(function saveTodo(loadTodoReturn){});

Categories

Resources