Reputation: 39
I'm using MeanJS and the user inputs a list of objects that each need to create a new document. Simultaneously I need to create another separate document with pointers to each of those objects from the array and link each of those objects back to this new document as well. So the final outcome needs to be an arbitrary number of documents of model 'Q' that are linked to one other document of model 'S'.
The reason I'm trying to do this is to allow a user to create a survey of questions. Each question will be its own object that fills in the Survey (which, as one property, will contain a list of those question IDs).
S = {"_id": 0, "Qids": [ObjectId("1"), ObjectId("2"), ObjectId("3"), ObjectId("4")]}
Q1 = {"_id": ObjectId("1"), "Sid": ObjectId("0")}
Q2 = {"_id": ObjectId("2"), "Sid": ObjectId("0")}
Q3 = {"_id": ObjectId("3"), "Sid": ObjectId("0")}
Q4 = {"_id": ObjectId("4"), "Sid": ObjectId("0")}
My problem: I can't seem to do this without running into some sort of problem with callbacks. Could anybody give me some advice? This is what it looks like right now:
Client Side:
$scope.Qlist = [Q1, Q2, Q3, Q4];
$scope.S = {};
$http.post('/S', $scope.S).success(function(data){
var req_obj = {
Sid: data._id,
Q: {}
};
for (var i = 0; i<$scope.Qlist.length; i++) {
req_obj.Q = $scope.Qlist[i];
$http.post('/Q', req_obj);
};
});
Server Side:
app.route('/Q')
.post(users.requiresLogin, questions.hasAuthorization, questions.fillSurvey);
And then I have server-side controllers that handle those functions. The questions.fillsurvey function adds the questions to MongoDB and then takes the ids of each question and pushes them into the S document under Qids. Most of this works fine, BUT while the client is sending Q1, Q2, Q3, and Q4, the server is only receiving Q4, four times.
Ideally, I'd like to send $scope.Qlist
and $scope.S
together in just one post request and have the server side figure it all out, but I keep getting caught with the callback functions, which is why instead I've opted to loop the post through $scope.Qlist
on the client side. If anybody has a "best practices" solution to this, I'd really appreciate the help!
Upvotes: 1
Views: 27
Reputation: 727
Short Answer: you need to define req_obj
inside your for
loop.
Long Answer: JavaScript relies on things called closures to handle variable scoping. JavaScript is also an asynchronous language. This means that in JS, your for loop will not wait for the $http.post to finish before continuing.
By putting req_obj outside of the for loop, the asynchronous part of JS is modifying req_obj.Q 4 times before the first $http finishes preparing and firing. Moving the req_obj into the for loop takes it out of the closure above, and puts it into the closure of the for loop, which is similar to an anonymous function.
Upvotes: 1