Why promise chains can be flattened? - javascript

The following code contains two kinds of promise chain, seems they'r equivalent, but I don't understand why they are equivalent. I think of it like 2*(3+4) = 2*3+4, which is not correct.
// example1
runAsync1()
.then(function(data1){
return runAsync2()
.then(function(data2){
return runAsync3();
})
})
.then(function(data3){
console.log(data3);
});
// example 2
runAsync1()
.then(function(data1){
return runAsync2();
}).then(function(data2){
return runAsync3();
}).then(function(data3){
console.log(data3);
});

Maybe some braces would help you understand this a little better. (NOTE: this is exactly the same thing as you had except with an extra set of braces on the return)
// example1
runAsync1()
.then(function(data1){
return (
runAsync2()
.then(function(data2){
return runAsync3();
})
)
})
.then(function(data3){
console.log(data3);
});
So what is happening here,
.then is called on runAsynch1()
.then is then called on runAsynch2() which returns runAsynch3() (this return carries on all the way down the chain of returns)
finally .then is called on the returned runAsynch3()
As you can see, this is exactly the same process as what happens in example 2
// example 2
runAsync1()
.then(function(data1){
return runAsync2();
}).then(function(data2){
return runAsync3();
}).then(function(data3){
console.log(data3);
});

It's a little bit implementation-specific, but the magic, regardless of the specifics is in the then.
Then does a couple of things.
The TL;DR is that then subscribes to returned promise chains, but below are examples closer to the guts of a promise.
The first thing is:
"Is the promise still pending? Then schedule these callbacks for later; otherwise, schedule this callback to run on the next tick (setTimeout(handle, 0)). Return a new promise that resolves/rejects to the eventual value."
// basically accurate-ish
then (onSuccess, onError) {
return new Promise((resolveNext, rejectNext) => {
if (myPromiseIsDone) {
// I already have the value; run the next step ASAP
// this is ugly, but hopefully it proves a point
runOnNextTick(onSuccess, onError, promiseResult, resolveNext, rejectNext);
} else {
// I don't have a result yet; come back when it's ready
scheduleWhenDone(onSuccess, onError, resolveNext, rejectNext);
}
});
}
The second is where your answer lies:
"Run the handler. Get the return value from the callback passed to then. Is the return value a Thenable object (has a then method)? Then call then and pass in the resolve/reject functions that control my promise... otherwise, resolve/reject accordingly, based on whether it throws or returns."
// entirely subjective and implementation-specific,
// but the algorithm is almost spec-compliant
handleSuccess (onSuccess, resolveNext, rejectNext, value) {
if (!onSuccess) {
// if they didn't give me a `then(callback)`,
// just pass the value to the next promise
resolveNext(value);
return;
}
try {
// I'm running the `then(callback)` here
const result = onSuccess(value);
if (hasThenMethod(result)) {
// it's promise-like, subscribe
result.then(resolveNext, rejectNext);
} else {
resolveNext(result);
}
} catch (err) {
// something blew up, while trying to succeed, so fail
rejectNext(err);
}
}
Reject looks similar.
So the outer then subscribes to the inner then.
If you ever wanted to get into functional programming, the ES6 Promise is almost a monad.
The difference is that a monad would force you to have a different method, to tell it to chain to the returned promise, rather than doing it automatically.
then is basically the same as map on arrays. You call then, pass it a function that gets the value and returns a new promise with the transformed value.
So a monadic promise might be one that has map and chain, or then and chain, where chain does almost exactly the same thing but says "hey, then, this callback is going to return a promise; subscribe to that one, so that you flatten it out, rather than returning a promise of a promise of a value".
That's almost all it would take to be a monad.
Hope that all helps.

Related

What is the difference between Promise.resolve(thenable) and new Promise(thenable.then)?

The question is the title. I'm trying to get a deeper understanding of promises and I think I've figured out how Promise.resolve(thenable) works, or at least mostly how it works, looking at the examples on MDN. I'm wondering if there's a difference between the two. I whipped up this example to show them behaving the same, in way that I would think would show differences in behaviour if there was going to be any. But obviously this test alone isn't good enough to conclude there's nothing different about them, so I've come here.
let thenable = {
then(resolve) {
setTimeout(()=>{
resolve((()=>{
console.log('test');
return thenable;
})());
}, 1000);
},
};
let p1 = Promise.resolve(thenable);
let p2 = new Promise(thenable.then);
In your example, the two work mostly the same. You're right, passing resolve and reject to the then method invocation of a thenable is what basically happens when you are resolving a promise with the thenable object.
However, there are a few differences:
the then method of a thenable is called as a method on (with the this context as) the thenable object, unlike your new Promise(thenable.then) does - a .bind(thenable) would fix that.
Promise.resolve (obviously) has to check first whether the passed object is a thenable at all, it also handles obscure cases where accessing (not calling) .then throws
a subtle discrepance in timing: Promise.resolve schedules even the then call asynchronously:
Promise.resolve({
get then() {
console.log("property access");
return function(res, rej) {
console.log("method call");
res("fulfillment");
};
}
}).then(console.log);
console.log("sync execution end");
There shouldn't be any difference between these two constructs (Promise.resolve(thenable) and new Promise(thenable.then))
Both support resolve, reject as parameters.
If an error is thrown within the then(resolve) { ... } it will be implicitly catched and the promise will be rejected.
Resolving then(resolve) { ... } with thenable would result in infinite recursion.

Race condition issues with async functions Javascript [duplicate]

I would like to get a deeper understanding of how Promises work internally.
Therefore I have some sample code:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Here a link to execute this code.
As you would predict, first p1 is resolved, afterwards p2 and in the end the final then prints the resolv value.
But the API ref states the following:
"then" returns a new promise equivalent to the value you return from
onFulfilled/onRejected after being passed through Promise.resolve
So it would be interesting to know WHEN exactly the "then" function is executed?
Because the final "then" in the code is chained to the chainPromises(), I first thought that
it would execute after the function chainPromises() returns something (in this case another promise).
If this would have been the case the "val" of the final "then" function would be the returned promise.
But instead, the final "then" waits until all promises inside the first "then" which are returned have been resolved.
This absolutely makes sense because in this way, the "then" functions can be stacked, but
I do not really get how this is done, since the API spec. does not really cover what "then" returns and when the "then" functions is executed.
Or in other words, why does the final "then" function wait until all the Promises are resolved inside the chainPromises() function instead of just waiting for the first returned object as the API doc says.
I hope I could make clear what I mean.. :)
About Promise resolution
The thing you're witnessing here is called recursive thenable resolution. The promise resolution process in the Promises/A+ specification contains the following clause:
onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)
The ES6 promise specification (promises unwrapping) contains a similar clause.
This mandates that when a resolve operation occurs: either in the promise constructor, by calling Promise.resolve or in your case in a then chain a promise implementation must recursively unwrap the returned value if it is a promise.
In practice
This means that if onFulfilled (the then) returns a value, try to "resolve" the promise value yourself thus recursively waiting for the entire chain.
This means the following:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
So for example:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
And that:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
Is it a good idea?
It's been the topic of much debate in the promises specification process a second chain method that does not exhibit this behavior was discussed but decided against (still available in Chrome, but will be removed soon). You can read about the whole debate in this esdiscuss thread. This behavior is for pragmatic reasons so you wouldn't have to manually do it.
In other languages
It's worth mentioning that other languages do not do this, neither futures in Scala or tasks in C# have this property. For example in C# you'd have to call Task.Unwrap on a task in order to wait for its chain to resolve.
Let's start with an easy perspective: "chainPromises" returns a promise, so you could look at it this way:
// Do all internal promises
var cp = chainPromises();
// After everything is finished you execute the final "then".
cp.then(function(val) {
console.log(val);
});
Generally speaking, when returning a promise from within a "then" clause, the "then" function of the encapsulating promise will be marked as finished only after the internal "then" has finished.
So, if "a" is a promise, and "b" is a promise:
// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.
var c = a.then(function () {
return b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
So the output will be:
B!
Done!
Notice btw, that if you don't "return" the internal promise, this will not be the case:
// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.
var c = a.then(function () {
// Notice we're just calling b.then, and don't "return" it.
b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Here we can't know what would be outputted first. It could be either "B!" or "Done!".
Please check the below example regarding how promises works:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
console.log('person1: shoe ticket');
console.log('person2: shoe ticket');
const promiseGirlFriendBringingTickets = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ticket');
}, 3000);
});
promiseGirlFriendBringingTickets.then((t) => {
console.log(`person3: show ${t}`);
})
console.log('person4: shoe ticket');
console.log('person5: shoe ticket');
Promise then return promise object, not promise's resolved value. I forked your JsFiddle, and added some of mine try this.
promise.then is executed right after that promise object is resolved.
I do not know how this is done in actual promises libraries, but I was able to re-create this functionality in the following way:
1) each promise has a waitingPromises property;
2) then method returns a new promise, and the original promise's waitingPromises property points to the new promise.
In this way, the chain of .then()s creates a structure that is similar to a linked list or rather a tree (each promise can have several waiting promises). A promise can be resolved only after its 'parent' promise has been resolved. The .then method itself is executed immediately, but the corresponding promise that it creates is resolved only later.
I am not sure this is a good explanation and would love to learn about other possible approaches.
Normally code is synchronous - one statement executes like (fileopen) and there is a guarantee that the next statement will execute immediately afterwards like filewrite()
but in asynchronous operations like nodejs, you should assume that
you have no idea when the operation will complete.
You can't even assume that just because you send out one request first, and another request second, that they will return in that order
Callbacks are the standard way of handling asynchrnous code in JavaScript
but promises are the best way to handle asynchronous code.
This is because callbacks make error handling difficult, and lead to ugly nested code.
which user and programmer not readble easily so promises is the way
You can think of Promise as a wrapper on some background task. It takes in a function which needs to be executed in the background.
The most appropriate place to use a promise is where some code is dependent on some background processing and it needs to know the status of the background task which was executed. For that, the background task itself accepts two callback resolve and reject in order to convey its status to the code which is dependent on it. In layman terms, this code is the one behind it in the promise chain.
When a background task invokes resolve callback with some parameter. it's marking the background operation successful and passing the result of the background operation to the next then block which will be executed next. and if it calls reject, marking it as unsuccessful then the first catch block will be executed.
In your custom promise, you can pass an error obj to the reject callback so that next catch block is aware of the error happened in the background task.

Break out of a Promise "then" chain with errorCallback

-- EDIT --
I encountered a weird thing recently about promises, but I guess it's maybe because it's against the philosophy of promises.
Considering the following code :
// Assuming Auth is just a simple lib doing http requests with promises
Auth.signup()
.then(succCall, errCall)
.then(loginSucc, loginErr)
// My callbacks here
function succCall (){
// OK, send second promise
console.log('succCall');
return Auth.login();
}
function errCall(){
// I do some things here and now
// I want to break out from here
console.log('errCall');
}
function loginSucc(){
// This is the callback of the login method when it went OK
// I want to enter here ONLY if with go through the succCall
console.log('loginSucc');
}
function loginErr(){
// This is the callback of the login method when it went not ok
// I want to enter here ONLY if with go through the succCall
console.log('loginErr');
}
Here if something goes wrong in Auth.signup(), this is what show :
errCall, loginSucc
if i do a $q.reject() in the errCall this is what happens :
errCall, loginErr
and this is what i want :
errCall... finish, stop here
Now, the problem is, it goes in errCall when signup goes wrong, that's good, but then it enters loginSucc...
I want to break out of the then chain when any errorCallback (which is errCall or loginErr here) is encountered.
-- EDIT --
I think i was misunderstood by some mean, i want to totally break the chain without check in any other "then" if something went wrong.
As if i was saying : if first then is wrong stop here, if first then ok continue, if second "then" ok continue, if third "then" wrong, stop
// Just like if i did the following but by chainning "then" methods
// My callbacks here
function succCall (){
// OK, send second promise
return Auth.login().then(loginSucc, loginErr);
}
My point is, i don't want only one error handler if i have many "then" chained
What is effectively happening is this:
try {
try {
var a = succCall();
} catch(e1) {
a = errCall(e1);
}
var b = loginSucc(a);
} catch(e2) {
b = loginErr(e2);
}
You can break out of the chain by calling
return $q.reject('Reason Err was called');
in your errCall() function.
EDIT:
As OP remarked by calling $q.reject the code will enter the loginErr function.
Alternatively you can modify your code like this:
Auth.signup()
.then(function(a) {
succCall()
return loginSucc(a).then(null, loginErr);
}, errCall)
You can read more in these two SO question:
Break promise chain
Break Out of then promises in
Angularjs
This also is a helpful read : Flattening Promise Chains
errCall function needs tor return a promise, and that promise needs to be rejected for loginErr to be fired.
function errCall(){
// i do some things here and now
return $q(function(resolve, reject) {
// auto reject
reject();
});
}
Alternatively try .catch:
Auth.signup()
.then(succCall)
.then(loginSucc)
.catch(function(err){
// caught error, problem is you won't know which function errored out, so you'll need to look at the error response
});
Just don't pass any errCall or loginErr to then and use catch() in the end of the promise chain and it will be interrupted on first error, which will be passed to catch(). If you want explicitly process error of Auth.signup() then your errCall should look like this:
function (err) {
if(isFatal(err)) {
return Promise.reject(new Error('Fatal!')); //`catch()` handler will be called with `new Error('Fatal!')`
} else {
return 'something'; //next `then()` handler will be called with 'something'
}
}
Your best option is to return a promise that is never resolved from errCall():
function errCall() {
console.log('errCall');
return $q.defer().promise;
}
But you are right, what you are trying to do is "against the philosophy of promises".
Why you shouldn't do it
It is of course a problem that your loginSucc function is called when an error occurs during evaluation of the first promise. However, that can be fixed by rejecting once again in errCall as others have already pointed out. But you should not try to avoid the execution of loginErr, otherwise something is conceptually wrong with your code.
The evaluation of the expression
Auth.signup().then(succCall, errCall)
yields another promise. The contract is that a promise has a then() method taking two callbacks as parameters, one for success and one for failure. The contract is also that the success callback is called when the promise is evaluated successfully and that the error/failure callback is called in all other cases. If you intend to never call either of those, don't use a promise!

Optional Promise API

I have a validation library that is purely synchronous but is often used as part of a chain of async functions. However, I have to maintain an existing synchronous API and would like to make the promise API optional.
Can I somehow detect (at runtime) whether a function is part of a Promise chain?
This is pretty easy with callbacks since you can just check if a callback was passed in. I understand that I could pass in an optional promise boolean, but that seems inelegant.
I've also considered doing a callback interface and using a library to convert the callback interface to a promise based interface on the fly. However, I'm working in Haxe and I would prefer to keep the transforms/abstractions down to a minimum.
I also understand that you can sandwich regular functions in-between promises, but there are some instances where the behavior would differ between the two.
FINAL Edit Lots of confusion as to why I can't just return the same values, first example (below) didn't seem to help. Remember, this is still simplified.
//mix of sync with promise
new Promise(function(resolve, reject){
var safeToAdd = thingTracker.preflight(newThing);
if(safeToAdd){
return client.request.addThing(newThing); //send request to server
} else {
reject(newThing.errorMessages); //requires explicit reject, cannot just pass results along
}
}).then(function(newThing){ //client and server both cool with newThing?
thingTracker.save(newThing);
}).catch(function(errorMessages){ //handles errorMessages from client and server
ui.show(errorMessages);
});
//pure promise
thingTracker.preflight(newThing).then(function(){
return client.request.addThing(newThing); //sends request to server
}).then(function(newThing){ //client and server both cool with newThing?
thingTracker.save(newThing);
}).catch(function(errorMessages){ //handles errorMessages from client and server
ui.show(errorMessages);
});
(Old) Edit to clarify (but didn't really):
function preflight(thing){
var validity = thing === 42;
if(promise){
if(validity){
return Promise.resolve(validity);
} else {
return Promise.reject(validity);
}
} else {
return validity;
}
}
Obviously I can do the same checks in a then's anon function, but that is not much better than using the sync interface directly. Also note that this is a very simple example, in the real function there are side effects on thing and messages are produced.
Edit Just to illustrate my point a bit better, here is a gist of what things look like.
Synchronous functions can be used within a promise chain just fine. If you have a synchronous API call that is called like this:
var info = myApi("foo");
That can be used just fine within a promise chain:
someAsyncCall().then(myApi).then(someOtherFunction)
You don't need to make myApi async or return a promise to be used this way. The only thing you can't do in a promise chain with a synchronous function is that it can't be the first item in the chain, but then it doesn't need to be. Since it's synchronous, it can just be called before you start the chain if anyone wants it to execute first. Or, worst case, you can do:
Promise.resolve().then(myAPI).then(someOtherFunction);
Can I somehow detect (at runtime) whether a function is part of a
Promise chain?
No, you cannot (unless you explicitly pass it some info that tells it that) and you do not need to in order to use it in a promise chain. You do not need to return a promise to be a .then() handler. You can just return a value and that value will become the value of the promise chain at that point in the chain.
I also understand that you can sandwich regular functions in-between
promises, but there are some instances where the behavior would differ
between the two ... such as returning false vs throwing a message.
It is not clear to me why the behavior would have to be different. If returning false is your normal synchronous behavior, you can do that just fine in a promise chain - the next step in the chain just needs to handle the false value that is passed to it, just like the next line of synchronous code would do. If throwing an exception is your normal behavior, you can do that just fine in a promise chain too (the promise chain will turn the exception into a rejection) which the following code can decide how it wants to handle. One can make a good argument that it would be worse if your synchronous function behaved differently based on whether it was part of a promise chain or not. If you see a good reason for two different behaviors, then you should probably have either two different functions (that can be documented differently) or an option passed in that determines the behavior.
Comment based on the code you added in your edit
You seem to think that when called via a promise chain that you need to return a resolved or rejected promise chain. You do not need to do that. You can just return a normal value and the promise chain will inherit the value you return. There is really no reason to return a resolved or rejected promise unless you want it to be the first function in a promise chain, but in that case, it isn't in a promise chain yet anyway so you could never detect that. And, there's no reason for a synchronous operation to be the first one in a promise chain. Just call the synchronous operation first and then initiation your promise chain with the async operations.
Here's a demo of a synchronous function being used in a promise chain:
function log(str) {
var div = document.createElement("div");
div.innerHTML = str;
document.body.appendChild(div);
}
// test async call
function delay(t, val) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(val);
}, t);
});
}
function square(x) {
return x * x;
}
log("Calculating the square of 9");
delay(500, 9).then(square).then(function(result) {
log("Result = " + result);
});
Or, you can even do this to initiate a promise chain with your synchronous operation as the first operation in the chain:
function log(str) {
var div = document.createElement("div");
div.innerHTML = str;
document.body.appendChild(div);
}
function square(x) {
return x * x;
}
log("Calculating the square of 9");
Promise.resolve(9).then(square).then(function(result) {
log("Result = " + result);
});
I believe promises have only one argument so it's not possible to pass an isPromise boolean through the chain, even if you could, you'd have to consciously add the parameter, so why not just call the async function...
function preflight(thing){
return thing === 42;
}
function preflightAsync(thing){
return new Promise(resolver);
function resolver(resolve,reject){
setTimeout(function foo(){
preflight(thing) ? resolve(true,"this won't make it") : reject();
},1000);
}
}
// Promised
preflightAsync(42).then(doSomethingWithIt).catch(doSomethingWithIt);
preflightAsync(89).then(doSomethingWithIt).catch(doSomethingWithIt);
// Call Directly
doSomethingWithIt(preflight(42));
doSomethingWithIt(preflight(89));
function doSomethingWithIt(result,nada){
result = result ? "BAM!!!" : "WAM!!!";
console.log("doSomethingWithIt",result,nada);//doSomethingWithIt BAM!!! undefined
return result;
}
These examples use the new native Promise function, browser support is limited.
As we can see from previous answers you can't use exactly the same function also for Promises. Adding my workaround here which is unfortunately extending the function prototype ...
The problem is that if you want to use the same function synchronously and in a Promise the use of arguments would differ.
As an example - a function truncating a string:
sync:
truncate('A very long string coming from a sync. operation', 10);
async:
Promise.resolve('A very long string coming from a network request')
.then( truncate(10) )
The async version would make the truncate Function think that 10 is the string and you would need to check typeof in every function or do ducktyping.
What would work:
Promise.resolve('A very long string coming from a network request')
.then( truncate.it(10) )
if you extended the function prototype before:
Function.prototype.it = (function() {
return function() {
var args = arguments;
return function(){
Array.prototype.push.apply(arguments, args);
return this.apply(null, arguments);
}.bind(this);
};
}());
function foo(a, b, c) {
console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
};
// LOGIC :
foo(1, 2, 3);
// SAME AS
foo.it(2, 3)(1);
// OR
foo.it(3)(1, 2);
// OR pretty useful for .then()
Promise.resolve(1).then(foo.it(2, 3));
fiddle

What happens in a Parse Promise then block when execution reaches end of block before a return is encountered?

Suppose I have the following Parse cloud code:
// assume myObj is a parse object
myObj.set("field1", "foo");
Parse.Promise.as().then(function()
myObj.save(myObj, {
success: function(savedObj) {
// A
return Parse.Promise.as();
},
error: function(myObj, error) {
// B
return Parse.Promise.as();
}
});
// C
// note that we can get here without any return statement being called
}).then(function() {
// D
});
(Now, i know it would be simpler to just use promises for the whole thing:
myObj.save().then(
...
...but there are some functions that don't return promises, so sometimes you have no choice but to mix Backbone-style success/error blocks with promises.)
My question:
What happens when C is reached? Does execution pause on this promise until one of those return statements is reached, and then execution reaches D? Does execution advance directly to D after reaching C, without waiting for a return statement? Is this an error?
In other words, is it possible for execution to happen in the order C, D, A/B? Or will it always be C, A/B, D? (Or, I suppose, if save finishes crazy fast, something like A/B, C, D?)
Your returns are from the inner functions. If it was up to me I'd promisify the save function itself. However, if you're convinced you don't want to do this you still have to return a Parse.Promise from the then if you want it to wait for anything.
The then function returns a new promise and resolves that promise (executes further thens) when its return value is resolved. If that's just a value it will not wait for anything - if it's a promise it will wait for it in turn to resolve.
Please look at how to promisify for further reading.
In your example - this would look something like:
myObj.set("field1", "foo");
Parse.Promise.as().then(function(){
var p = Parse.Promise();
myObj.save(myObj, {
success: p.resolve.bind(p), // on success, resolve the promise
error: p.reject.bind(p) // on failure, reject it
});
// any code here _will_ execute before the `then` is called.
return p; // return the promise so `then` will wait
}).then(function(savedObj) {
// this will always run after `myObj.save` completed
// you can add a catch handler for the error case
});
However, if we pay attention we can notice Parse's save method already returns a promise - Parse promisified it for us - so this code can be significantly reduced to:
myObj.set("field1", "foo");
Parse.Promise.as().then(function(){
return myObj.save(myObj)
}).then(function(savedObj) {
// this will always run after `myObj.save` completed
// you can add a catch handler for the error case
});
Which in turn can be reduced to:
myObj.set("field1", "foo");
myObj.save().then(function(savedObj){
// object save is done here
});
Answer seems to be that it won't wait for A or B -- it'll move on, probably with D executing before A or B.
In any case, it's basically a bug -- though not one the runtime will complain about -- to invoke asynchronous code (like I do with save()) but not explicitly return a local promise at the end of a then function block that would make the bigger promise wait until the asynchronous code finishes. In other words, I should do something like Benjamin Gruenbaum's answer suggests.
As a rule of thumb just keep returning promises, they will be automagically resolved. All Parse async methods return promises so just keep returning until you are done.
I wouldn't recommend to use the success and error methods. Using callbacks and promises together is not a good idea since you have to write a lot of extra code to account for it. If everything in your app return promises you can remove a block or add a another one very easily. Just create functions that return a promise.
Also, how you return promises while vary depending on the scope needed in each block.
So for example:
function myPromise (a) {
return Parse.Promise.as({name: 'David Bowie', a : a});
}
myObj.set("a", 1);
myObj.save(obj).then(function(obj) {
var a = obj.get('a');
return Parse.Promise.as()
.then(function() {
return Parse.Object.saveAll([])
.then(function() {
a += 1
return Parse.Promise.as(a);
})
})
}).then(function(a){
return myPromise(a);
})
.then(function(davidBowie) {
console.log(davidBowie.name);
console.log(davidBowie.a);
})
.fail(function() {
// handle error
})

Categories

Resources