Dynamic array promise sequence - javascript

Im getting dynamic (the number of promises can be change each per runtime) array of promises, Now I want that after every resolve or reject
to handle the returned promise before promises array will be finished .
I try with promise all but it's continue after all the promises has done.
if the array (of promises) wasn't be dynamic so I can simply use something like this
but I dont know how much promises I have in the array and I want after every promise fulfilled or ... to proceed with the answer of it and not wait until all the promises will done
firstMethod()
.then(secondMethod)
.then(thirdMethod);
We are using Q ...
Is it possible ?
Update (example )
Lets say I've the promise array
[promise1,promise2,promise3, promiseN]
Now I want that when promise1 finish to process to handle it with then and not wait that all promises will be finished .
The biggest issue here is the array can have N promises and I dont know in RT how much promises I will get until I got this array therefore I cannot use simply then
Update 2 (to clarify a bit more :-) ) The tricky part...
If I Know the size of the array beforehand I can use simply then , 5 entry in the array 5 chain with then but here the tricky part is that I dont know beforehand how much promises I will have in the array of the promises ....

If the goal is to chain each promise with same then but to not wait for all promises to complete, this is just a loop:
for (const promise of promiseArray) {
promise.then(...)
}
If promise results should be joined together in the end, the array can be additionally processed by all:
Promise.all(promiseArray.map(promise => promise.then(...)))
.then(...)
Notice that behaviour for all applies here. If there is uncaught rejection in promise array, only the first rejection will be caught.
This is true for most promise implementations. There may be Q methods that allow do do this easier.

you can use Promise.race()
The Promise.race(iterable) method returns a promise that resolves or rejects as soon as one of the promises in the iterable resolves or rejects, with the value or reason from that promise.
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([p1, p2]).then(function(value) {
console.log(value); // "two"
// Both resolve, but p2 is faster
});

If you don't need to chain promises. You could just do:
var tasks = [[promise1, handler1], [promise2, handler2], [promise3, handler3]];
tasks.forEach(function (task) {
var promise = task[0];
var handler = task[1];
promise.then(handler)
});

Related

Need help understanding Promise.all and async

This is the code I'm going to be talking about.
view: async (req, res, next) => {
let formato = req.query.formato || 'details';
try {
let mode = Client.getMode(formato);
let options = {
columns: mode.columns,
withRelated: mode.withRelated,
};
let client_promises = [ ]
req.query['ids'].map( id => {
let client = Client.findById(id, options);
client_promises.push(client)
})
let response = await Promise.all(cliente_promesas)
return res.json({ success: true, data: response });
} catch (error) {
return next(error);
}
},
I understand that the .map function iterates over an array of ids, which then is passed to Client.findById so it can return a promise to be fulfilled, getting the client's data when it resolves.
Now, those promises are pushed to an array, which then is passed to Promise.all, but I dont really understand where they are being resolved. Isnt Promise.all just passing a resolved promise when all promises in the array are resolved?
I also understand that await just makes the code wait for the resolution of the promise before continuing.
But where are the promises in client_promises being resolved?
I know this is basic but for the life of me I cant seem to read enough manuals and guides to be able to understand this.
All Promise.all does is wait for every Promise in the array passed to it to be done. It doesn't "fire" them. In fact every Promise in the array passed might even be in a resolved state. The Promises are "hot" from the moment they are created.
For your example, the function to get an item by id starts immediately and synchronously returns a Promise that will eventually resolve to whatever object is retrieved by id. This is key: the returning of the Promise is not the asynchronous part, it's the resolution.
Promise.all makes all the promises one big promise.
Consider the example below. I take 3 ids and do exactly what you do, I call findById and put what is returned by the function (a Promise) into an array, promises. In the findById, I also add an extra .then call to demonstrate how these Promises are "hot" and not waiting to be called by Promise.all. Also note that I still return the p.
By the time we actually get to the Promise.all, all of the Promises in promises have actually resolved, that's why you see them print to console first. They all take 100-600 milliseconds to resolve, but we actively wait a full 1000 milliseconds before we call Promise.all.
Unfortunately (kind of) there is no API to reveal the state of a Promise using the native implementation. I think there used to be ways with user land libraries like Bluebird and jQuery, but not with how the browser does it. Otherwise, we could inspect the Promise right before calling the Promise.all and see whether they were resolved or pending.
/**
* Utility function to wait a duration before resolving
* #param {number} [delay=100] How long to wait
* #returns {Promise<undfined>} Promise that will resolve after delay
*/
function timeout(delay = 100) {
return new Promise(resolve => {
setTimeout(resolve, delay);
});
}
/**
* Simulated find function that returns an object
* #param {number} id The id of the object to get
* #returns {Promise<object>} The fake DB object
*/
async function findById(id) {
await timeout((Math.random() * 500) + 100);
return {
id,
data: `foo-${id}`
};
}
(async function() {
const idsToGet = [1, 2, 3];
const promises = idsToGet.map(id => {
// Call to get the object
const p = findById(id);
// Let's add another listener here to know when they are done
p.then(r => {
console.log(`${r.id} is done`);
});
// Still return the actual Promise created by findById
return p;
});
// Just for kicks
await timeout(1000);
// Wait for EVERYTHING to be done
const res = await Promise.all(promises);
console.log(JSON.stringify(res, null, 4));
}());
Promise.all() takes list/ array of unresolved promises.
It is kind of like a big one promise that takes all the unresolved promises and until all of them are resolved the Promise.all() is unresolved.
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
In the above example, you can see that we are passing 3 promises to Promise.all()
and when all of them are fulfilled then only .then will be triggered.
in your case:
Client.findById(id, options);
must be returning a promise object which you are pushing into client_promises array.
and then feeding them to Promise.all(), until this point, your promises are just promises they are not resolved.
promise.all also returns a promise and as you have put await in front of it.
it will wait until of them re resolved and give you an array of resolved promises.
The promises are actually "fired" (that is, the code starts to run) when you do let client = Client.findById(id, options);. await Promise.all then waits until all of them are resolved or one of them is rejected in which case Promise.all also rejects with the value of the first promise rejection.

Promise returning a promise [duplicate]

I want to fulfill a promise with some other promise. The point is that I really want to get access to the (still pending) second promise as soon as the first promise is fulfilled. Unfortunately, I only seem to be able to get the second promise's resolution value once both both promises are fulfilled.
Here's the use case that I have in mind:
var picker = pickFile();
picker.then( // Wait for the user to pick a file.
function(downloadProgress) {
// The user picked a file. The file may not be available just yet (e.g.,
// if it has to be downloaded over the network) but we can already ask
// the user some more questions while the file is being obtained in the
// background.
...do some more user interaction...
return downloadProgress;
}
).then( // Wait for the download (if any) to complete.
function(file) {
// Do something with the file.
}
)
The function pickFile displays a file picker where the user may pick a file either from their own hard drive or from a URL. It returns a promise picker that is fulfilled as soon as the user has picked a file. At this point, we may still have to download the selected file over the network. Therefore, I cannot fulfill picker with the selected file as resolution value. Instead, picker should be fulfilled with another promise, downloadProgress, which in turn will eventually be fulfilled with the selected file.
For completenes, here's a mock implementation of the pickFile function:
function pickFile() {
...display the file picker...
var resolveP1 = null;
var p1 = new Promise(
function(resolve, reject) {
resolveP1 = resolve;
}
);
// Mock code to pretend the user picked a file
window.setTimeout(function() {
var p2 = Promise.resolve('thefile');
resolveP1(p2); // <--- PROBLEM: I actually want to *fulfill* p1 with p2
}, 3000);
return p1;
}
The problem in the marked line is that I would like to fulfill the promise p1 with the new promise p2, but I only know how to resolve it. The difference between fulfilling and resolving is that resolving first checks if the supplied value p2 is again a promise. If it is, then fulfillment of p1 will be deferred until p2 is fulfilld, and then p1 will be fulfilled with p2's resolution value instead of p2 itself.
I could work around this issue by building a wrapper around p2, i.e. by replacing the line
resolveP1(p2); // <--- PROBLEM: I actually want to *fulfill* p1 with p2
from the second code example by
resolveP1({promise: p2});
Then, in the first code example, I'd have to replace the line
return downloadProgress;
by
return downloadProgress.promise;
But this seems like a bit of a hack when all I really want to do is just fulfill (instead of resolve) a promise.
I'd appreciate any suggestions.
There doesn't seem to be a solution apart from the workaround I already described in the question. For future reference, if you want to fulfill (rather than resolve) a promise p with a value val, where val is another promise, then just calling the promise resolution function for p with argument val won't work as expected. It would cause p to be "locked in" on the state of val, such that p will be fulfilled with val's resolution value once val is fulfilled (see spec).
Instead, wrap val in another object and resolve p with that object:
var resolveP; // Promise resolution function for p
var p = new Promise(
function(resolve, reject) {
resolveP = resolve;
}
);
function fulfillPwithPromise(val) { // Fulfills p with a promise val
resolveP({promise: val});
}
p.then(function(res) {
// Do something as soon as p is fulfilled...
return res.promise;
}).then(function(res) {
// Do something as soon as the second promise is fulfilled...
});
This solution works if you already know that val is a promise. If you cannot make any assumptions about val's type, then you seem to be out of luck. Either you have to always wrap promise resolution values in another object, or you can try to detect whether val has a field then of type "function" and wrap it conditionally.
That said, in some cases the default behavior of promise resolution may actually have the desired effect. So only use the workaround described above if you are sure that you want to fulfill instead of resolve the first promise with the second one.
Although different people use different terms, in common terminology, "fulfill" means to put a promise in the "success" state (as opposed to "reject")--the state that will trigger then then handlers hanging off it.
In other words, you cannot "fulfill" a promise with a promise. You can fulfill it with a value. (By the way, the term "resolve" is usually meant as either of fulfilling or rejecting.)
What you can do is return a promise from a .then handler and that will have the effect of essentially replacing the original promise with the returned promise.
Here is a simple example of doing that:
asyncTask1 . then(asyncTask2) . then(processData)
where asyncTask1 is a promise, and asyncTask2 is a function which returns a promise. So when asyncTask1 is fulfilled (done successfully), then asyncTask2 runs, and the promise returned by the .then is "taken over" by the promise asyncTask2 returns, so that when it finishes, the data can be processed.
I can do something similar by calling Promise.resolve with a promise as parameter. It's a bit of a misnomer, because I'm not resolving the promise in the technical sense. Instead, the new promise created is "inhabited" by the promise I passed in. It's also useless, because using the result is exactly the same as using the promise I passed in:
Promise.resolve(asyncTask2)
behaves exactly the same as
asyncTask2
(assuming asyncTask2 is already a promise; otherwise Promise.resolve has the effect of creating a promise which is immediately fulfilled with the passed in value.)
Just as you can pass a promise to Promise.resolve, you can pass a promise to the resolve function provided to you as a parameter of the promise constructor callback. If the parameter you pass to resolve is a non-promise, the promise immediately fulfills with that value. However, if the parameter you pass to resolve is another promise, that promise "takes over the body" of the promise you are constructing. To put it another way, the promise you are constructing starts to behave exactly as the the promise passed to resolve.
By "behave exactly" I mean, if the promise you pass in to resolve is already fulfilled, the promise you are constructing is instantly fulfilled with the same value. If the promise you pass in to resolve is already rejected, the promise you are constructing is instantly rejected with the same reason. If the promise you pass in to resolve is not resolved yet, then any then handlers you hang off the promise you are constructing will be invoked if and when the promise you pass to resolve is resolved.
Just as it is confusing that Promise.resolve may result in a promise which is not actually resolved, it is similarly confusing that calling the resolve function handed to you as a parameter to the promise constructor may not actually resolve the promise being constructed if you call it with an unresolved promise. Instead, as I've said a couple of times now, it has the effect of putting the promise being constructed in a state of total congruence with the promise passed to resolve.
Therefore, unless I am missing the point of your question, pickfile could be written as
function pickFile() {
return new Promise(function(resolve, reject) {
...display the file picker...
// Mock code to pretend the user picked a file
window.setTimeout(function() {
resolve('thefile');
});
}
I didn't really understand your question clearly, so this might not be what you want. Please clarify if you care to.
Found a similar solution in the process of moving away from Angular's $q to the native Promise feature. Promise.all could be an option (in cases of independent parallel async tasks) by passing around an appropriate object, or something decorated with the state, passing it off to whatever is ready when appropriate. In the Promise.all sample below note how it recovers in one of the promises--took me awhile to realize how to redirect the result of a chain. The result of the all is just the last promise's return. While this doesn't answer the question's title, using return Promise.reject(<an-object-including-a-promise>) (or resolve) gives a series and/or group of async tasks shared access and control along the way. In the case of picking, downloading then working with a file I'd take out the progress-event handling then do: pickFile.then(download,orFailGracefully) with downloadProgress handled within the download onResolve handler (download-progress doesn't appear to be an async task). Below are related experiments in the console.
var q = {
defer: function _defer(){
var deferred = { };
deferred.promise = new Promise(function(resolve, reject){
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
};
var communityThatCares = q.defer();
communityThatCares.promise.then(function(someGood){
console.log('someGood', someGood);
return someGood;
}, function(someBad){
console.warn('someBad', someBad);
return someBad;
});
(new Promise(function(resolve, reject){ communityThatCares.about = 'communityThatCares'; setTimeout(resolve,1000, communityThatCares); }))
.then(
function(e){
console.log(3,e); return e.resolve(e);
}, function(e){
console.warn(3, e); return e.reject(e);
});
var todo = {
find:'swan'
};
var greaterGood = [(
(new Promise(function(res,rej){ res(todo); })).then(function(e){ e.stuff = 'things'; return e; }),
(new Promise(function(res,reject){
reject(todo);
})).then(function(e){ return e; }
,function(e){
console.warn(1,e);
e.recover = 'uh oh';
return Promise.resolve(e);
}).then(function(e){ console.log(2,e); return e; }),
(new Promise(function(res,rej){ res(todo); })).then(function(e){ console.log(1,e); e.schedule = 'today'; return e; },function(e){ console.warn(1,e); return e; }).then(function(e){ console.log(2,e); return e; }))
];
var nkay = Promise.all( greaterGood )
.then(function(todo){
console.log('all',todo[0]); return todo;
}, function(todo){
console.warn('all',todo[0]); return todo;
});

Resolving promises synchronously with Q.all(promises)

I am using the Kriskowal Q library to handle promises.
I wrote the following function to wait until all promises have been resolved.
function multiplePromises(targetArray) {
var promises = {};
for (var i=0; i<targetArray.length; i++) {
var promise = singlePromise(); // any async. function
promises[i] = promise;
};
return Q.all(promises);
};
and I call it as follows:
multiplePromises(targetArray).then(
function(success){
console.log("success");
},
function(error){
console.log("error", error);
}
);
I was wondering however whether there is an order in which the promises are resolved (e.g. is it synchronous?). I.e. does the function wait to trigger the next promise i+1 until promise i is resolved? Or alternatively is it like with all other async. methods, that it actually fires all the single promises and just waits until they are all done?
If the second is the case, how would one rewrite this function to make sure that promise i+1 is ONLY triggered once promise i has been resolved?
Update: test
I did a test and put:
promises[i] = i;
to check whether it resolves sycnhronously and it seems the case. However, it could be just that my async function is fast enough to actually resolve it that quick. Does this seem right?
there are several ways to achieve what you want
Minimal change to your code would be
function multiplePromises(targetArray) {
var promises = [];
var p = Promise.resolve(); // I don't know the Q equivalent of this
for (var i=0; i<targetArray.length; i++) {
p = p.then(function() {
return singlePromise();
});
promises[i] = p;
};
return Q.all(promises);
};
The promises will be executed by Q in the order you declare them, but there's no way to ensure the return order will be the same. That is how async works.
If you want them to resolve in order, the only way I can think of is calling them one after the other instead of doing it in a batch.
This other response will provide more info and some solutions:
https://stackoverflow.com/a/36795097/7705625
Promises in theory could be resolved in order (and it could be easy to write an example in which they would) but you should never count on that.
The whole point of functions like Promise.all() (or Q.all() or Bluebird.all() etc.) is that if waits for all of the promises to get resolved, no matter what is the order of that, and as soon as they are all resolved then the promise that the Promise.all() itself returns gets resolved with an array of values that the original promises resolved to.
In that array you will get always the same order as the order of promises in the array that was an argument to Promise.all(). But the order in time in which the original promises were resolves is not known and is not relevant, as that will have no effect on the result of using Promise.all() whatsoever.

Wait for 1 promise and then all promises using $q

I'm fairly familiar with how $q works and I use it in angularjs to wait for single promises to resolve and multiple promises to resolve with $q.all().
The question is I'm not sure if its possible to do this (and if it works correctly): Can I wait for a single promise to resolve, but then also run some code when all my promises resolve too... AFTER the success callbacks of the individual promises have finished... for example:
var promises = [];
for(i=1, i<5, i++){
var singlePromise = SomeSevice.getData();
promises.push(singlePromise);
singlePromise.then(function(data){
console.log("This specific promise resolved");
});
}
// note: its important that this runs AFTER the code inside the success
// callback of the single promise runs ....
$q.all(promises).then(function(data){
console.log("ALL PROMISES NOW RESOLVED"); // this code runs when all promises also resolved
});
My question is, does this work as I think it does, or is there some weird async, indeterministic result risk?
A call to then also returns a promise. You can then pass this to your array instead of the original promise. This way your $q.all will run after all your thens have been executed.
var promises = [];
for(i=1, i<5, i++){
// singlePromise - this is now a new promise from the resulting then
var singlePromise = SomeSevice.getData().then(function(data){
console.log("This specific promise resolved");
});
promises.push(singlePromise);
}
$q.all(promises).then(function(data){
console.log("ALL PROMISES NOW RESOLVED");
});

Fulfill (don't resolve) promise with another promise

I want to fulfill a promise with some other promise. The point is that I really want to get access to the (still pending) second promise as soon as the first promise is fulfilled. Unfortunately, I only seem to be able to get the second promise's resolution value once both both promises are fulfilled.
Here's the use case that I have in mind:
var picker = pickFile();
picker.then( // Wait for the user to pick a file.
function(downloadProgress) {
// The user picked a file. The file may not be available just yet (e.g.,
// if it has to be downloaded over the network) but we can already ask
// the user some more questions while the file is being obtained in the
// background.
...do some more user interaction...
return downloadProgress;
}
).then( // Wait for the download (if any) to complete.
function(file) {
// Do something with the file.
}
)
The function pickFile displays a file picker where the user may pick a file either from their own hard drive or from a URL. It returns a promise picker that is fulfilled as soon as the user has picked a file. At this point, we may still have to download the selected file over the network. Therefore, I cannot fulfill picker with the selected file as resolution value. Instead, picker should be fulfilled with another promise, downloadProgress, which in turn will eventually be fulfilled with the selected file.
For completenes, here's a mock implementation of the pickFile function:
function pickFile() {
...display the file picker...
var resolveP1 = null;
var p1 = new Promise(
function(resolve, reject) {
resolveP1 = resolve;
}
);
// Mock code to pretend the user picked a file
window.setTimeout(function() {
var p2 = Promise.resolve('thefile');
resolveP1(p2); // <--- PROBLEM: I actually want to *fulfill* p1 with p2
}, 3000);
return p1;
}
The problem in the marked line is that I would like to fulfill the promise p1 with the new promise p2, but I only know how to resolve it. The difference between fulfilling and resolving is that resolving first checks if the supplied value p2 is again a promise. If it is, then fulfillment of p1 will be deferred until p2 is fulfilld, and then p1 will be fulfilled with p2's resolution value instead of p2 itself.
I could work around this issue by building a wrapper around p2, i.e. by replacing the line
resolveP1(p2); // <--- PROBLEM: I actually want to *fulfill* p1 with p2
from the second code example by
resolveP1({promise: p2});
Then, in the first code example, I'd have to replace the line
return downloadProgress;
by
return downloadProgress.promise;
But this seems like a bit of a hack when all I really want to do is just fulfill (instead of resolve) a promise.
I'd appreciate any suggestions.
There doesn't seem to be a solution apart from the workaround I already described in the question. For future reference, if you want to fulfill (rather than resolve) a promise p with a value val, where val is another promise, then just calling the promise resolution function for p with argument val won't work as expected. It would cause p to be "locked in" on the state of val, such that p will be fulfilled with val's resolution value once val is fulfilled (see spec).
Instead, wrap val in another object and resolve p with that object:
var resolveP; // Promise resolution function for p
var p = new Promise(
function(resolve, reject) {
resolveP = resolve;
}
);
function fulfillPwithPromise(val) { // Fulfills p with a promise val
resolveP({promise: val});
}
p.then(function(res) {
// Do something as soon as p is fulfilled...
return res.promise;
}).then(function(res) {
// Do something as soon as the second promise is fulfilled...
});
This solution works if you already know that val is a promise. If you cannot make any assumptions about val's type, then you seem to be out of luck. Either you have to always wrap promise resolution values in another object, or you can try to detect whether val has a field then of type "function" and wrap it conditionally.
That said, in some cases the default behavior of promise resolution may actually have the desired effect. So only use the workaround described above if you are sure that you want to fulfill instead of resolve the first promise with the second one.
Although different people use different terms, in common terminology, "fulfill" means to put a promise in the "success" state (as opposed to "reject")--the state that will trigger then then handlers hanging off it.
In other words, you cannot "fulfill" a promise with a promise. You can fulfill it with a value. (By the way, the term "resolve" is usually meant as either of fulfilling or rejecting.)
What you can do is return a promise from a .then handler and that will have the effect of essentially replacing the original promise with the returned promise.
Here is a simple example of doing that:
asyncTask1 . then(asyncTask2) . then(processData)
where asyncTask1 is a promise, and asyncTask2 is a function which returns a promise. So when asyncTask1 is fulfilled (done successfully), then asyncTask2 runs, and the promise returned by the .then is "taken over" by the promise asyncTask2 returns, so that when it finishes, the data can be processed.
I can do something similar by calling Promise.resolve with a promise as parameter. It's a bit of a misnomer, because I'm not resolving the promise in the technical sense. Instead, the new promise created is "inhabited" by the promise I passed in. It's also useless, because using the result is exactly the same as using the promise I passed in:
Promise.resolve(asyncTask2)
behaves exactly the same as
asyncTask2
(assuming asyncTask2 is already a promise; otherwise Promise.resolve has the effect of creating a promise which is immediately fulfilled with the passed in value.)
Just as you can pass a promise to Promise.resolve, you can pass a promise to the resolve function provided to you as a parameter of the promise constructor callback. If the parameter you pass to resolve is a non-promise, the promise immediately fulfills with that value. However, if the parameter you pass to resolve is another promise, that promise "takes over the body" of the promise you are constructing. To put it another way, the promise you are constructing starts to behave exactly as the the promise passed to resolve.
By "behave exactly" I mean, if the promise you pass in to resolve is already fulfilled, the promise you are constructing is instantly fulfilled with the same value. If the promise you pass in to resolve is already rejected, the promise you are constructing is instantly rejected with the same reason. If the promise you pass in to resolve is not resolved yet, then any then handlers you hang off the promise you are constructing will be invoked if and when the promise you pass to resolve is resolved.
Just as it is confusing that Promise.resolve may result in a promise which is not actually resolved, it is similarly confusing that calling the resolve function handed to you as a parameter to the promise constructor may not actually resolve the promise being constructed if you call it with an unresolved promise. Instead, as I've said a couple of times now, it has the effect of putting the promise being constructed in a state of total congruence with the promise passed to resolve.
Therefore, unless I am missing the point of your question, pickfile could be written as
function pickFile() {
return new Promise(function(resolve, reject) {
...display the file picker...
// Mock code to pretend the user picked a file
window.setTimeout(function() {
resolve('thefile');
});
}
I didn't really understand your question clearly, so this might not be what you want. Please clarify if you care to.
Found a similar solution in the process of moving away from Angular's $q to the native Promise feature. Promise.all could be an option (in cases of independent parallel async tasks) by passing around an appropriate object, or something decorated with the state, passing it off to whatever is ready when appropriate. In the Promise.all sample below note how it recovers in one of the promises--took me awhile to realize how to redirect the result of a chain. The result of the all is just the last promise's return. While this doesn't answer the question's title, using return Promise.reject(<an-object-including-a-promise>) (or resolve) gives a series and/or group of async tasks shared access and control along the way. In the case of picking, downloading then working with a file I'd take out the progress-event handling then do: pickFile.then(download,orFailGracefully) with downloadProgress handled within the download onResolve handler (download-progress doesn't appear to be an async task). Below are related experiments in the console.
var q = {
defer: function _defer(){
var deferred = { };
deferred.promise = new Promise(function(resolve, reject){
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
};
var communityThatCares = q.defer();
communityThatCares.promise.then(function(someGood){
console.log('someGood', someGood);
return someGood;
}, function(someBad){
console.warn('someBad', someBad);
return someBad;
});
(new Promise(function(resolve, reject){ communityThatCares.about = 'communityThatCares'; setTimeout(resolve,1000, communityThatCares); }))
.then(
function(e){
console.log(3,e); return e.resolve(e);
}, function(e){
console.warn(3, e); return e.reject(e);
});
var todo = {
find:'swan'
};
var greaterGood = [(
(new Promise(function(res,rej){ res(todo); })).then(function(e){ e.stuff = 'things'; return e; }),
(new Promise(function(res,reject){
reject(todo);
})).then(function(e){ return e; }
,function(e){
console.warn(1,e);
e.recover = 'uh oh';
return Promise.resolve(e);
}).then(function(e){ console.log(2,e); return e; }),
(new Promise(function(res,rej){ res(todo); })).then(function(e){ console.log(1,e); e.schedule = 'today'; return e; },function(e){ console.warn(1,e); return e; }).then(function(e){ console.log(2,e); return e; }))
];
var nkay = Promise.all( greaterGood )
.then(function(todo){
console.log('all',todo[0]); return todo;
}, function(todo){
console.warn('all',todo[0]); return todo;
});

Categories

Resources