Is there a way to save a list of models synchronously, waiting for response from previous save before saving another one?
You might want to schedule them using Ember.run
, check out the following link:
http://emberjs.com/guides/understanding-ember/run-loop/#toc_an-example-of-the-internals
DS.Model.save returns a promise, so wait until the promise resolves to save the next model:
model.save(attrs).then(function() {
nextModel.save();
}, function() {
// error handling
});
What if I have an array of 10 objects that I want to save one after another?
Code:
var arr = [item1,item2,item3];
function finishFunction() {
console.log('done');
}
function errorFunction() {
console.log('error');
}
function runNextOrFinish() {
var next = arr.shift();
if (next) {
next.save().then(runNextOrFinish, errorFunction);
} else {
finishFunction();
}
}
function main() {
runNextOrFinish();
}
Run:
main();
I would think something like that should work
Also:
function chainPromise(promise, obj) {
if (!promise) {
return obj.save();
} else {
return promise.then(function() {
return obj.save();
});
}
}
var arr = [inst1, inst2, inst3, inst4];
var thisItem, rootPromise = null;
for (var i=0, len=arr.length; i<len; i++) {
rootPromise = chainPromise(rootPromise, arr[i]);
}
That’s kind of an interesting question. I think others have shown good examples of using promises. I’d love to hear about your use case. When I read the title I thought you meant saving a list of objects “transactionally”, but your description is clear.
Reduce would work well in this case
var chainedPromises = models.reduce(function(previous, model){
return previous.then(model.save);
}, Ember.RSVP.resolve());
Note, I haven’t actually run this
I think you would need to bind the model.save
to ensure thisArg
is correct. E.g.
var chainedPromises = models.reduce(function(previous, model){
return previous.then(model.save.bind(model));
}, Ember.RSVP.resolve());
Other than that, Map/Reduce programming FTW.
I didn’t know you could do that with bind, very useful.
Yeap, that’s the native bind. FYI it doesn’t work on some old browsers (see: Function.prototype.bind() - JavaScript | MDN). There are some bind polyfills floating around if you need.
Also another FYI for anyone using bind to wrap up a callback, it’s generally a good idea to use Ember.run.bind
because it guarantees you’re inside of a runloop, however in this case it’s not necessary because promises are always resolved in a runloop.