Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gathering multiple promise results? (plain javascript)

I'm new to Promises and trying to load lots of results from localstorage first and if that fails, fall back on getting the data from a server. I don't want to use jquery - ignore that I'm currently using $.getJSON :-/

function loader1() {
    return new Promise(function (resolve, reject) {
        localforage.getItem("data1").then(function (value) {
            if (value !== null) {
                resolve(value);
            } else {
                $.getJSON("/myapp/data1.json").then(function (data) {
                    if (data !== null) {
                        resolve(data);
                    }
                }).catch(function (err) {
                    reject(err);
                });
            }
        });
    });
}

which is fine for one file. So then I'd

loader1().then(function(result) { 
    // we have a result
    doSomethingElse();
}).catch(function (err) {
    // problem
});

But I want to do this for multiple files, some of which are in localstorage and some of which load json from a remote source. I want to load everything, and when it's finished, perform the next step of my app.

Promise.all appears to be the thing, but I can't see how to get the results of each of the loaders; I was thinking it would be like:

Promise
    .all([loader1, loader2, loader3])
    .then(function(result1,result2,result3)) {
        ...

but this isn't how it works ... so I tried

Promise
    .all([loader1, loader2, loader3])
    .then(function(result)) {
        // var result1 = result[0];
        // var result2 = result[1];
        // var result3 = result[1];

but the results of the second are the functions not the returned values ...

Searching many sites indicated that promise systems like Q and bluebird have a spread method which looks like what I want. can I do this in plain old javascript (how?) or should I look at using a library like Q or RSVP instead?

like image 792
frumbert Avatar asked Oct 13 '16 03:10

frumbert


1 Answers

but the results of the second are the functions not the returned values ...

You are not resolving any value form the Promise you construct. You are also not returning any values form the succeeding .then's in the chain. You need to do the following for each of your loader functions:

function loader1() {

    var data = localforage.getItem("data1");
    
    data.then(function (data) {

        if (data !== null) {
             return data;
        } else {
            data = $.getJSON("/myapp/data1.json")

            if (data !== null) {
                return data;
            } else {
                return Error;
        }

    data.catch(function (err) {
       return (err);
    }

This ensures that a call to function loader1() will either return a resolved Promise or a rejected Promise. You can then use the solution suggested by guest271314:

Promise
.all([loader1(), loader2(), loader3()])
.then(function(result) {
  // var result1 = result[0];
  // var result2 = result[1];
  // var result3 = result[1];
 })
 .catch(function (err) {
   // problem
 });

However please be aware that a Promise executes synchronously. This means that it does not automatically wait on any asynchronous action to complete inside the Promise. You have to take care of this yourself by only resolving it once the asynchronous action has completed (typically by resolving in a callback passed to an asynchronous function).

like image 184
rabbitco Avatar answered Sep 19 '22 12:09

rabbitco