javascriptpromiselocalforage

Chain promises with localforage


I am struggling with promises. I see how the chain of events is happening through .then().then().then().then().then().then().then().then().then().then().then().then() but I can not figure out how to make it end. I was hoping I could just make a simple :

 .then(callback(mydata))

However, I can't get that to work. I am trying to accomplish this.

function doSomethingCallback(theArrayComesBackHere) {
    theArrayComesBackHere.forEach(/*do stuff*/);
}    

button.onclick = () => {
   myobj.getlocalforagedata(doSomethingCallback);
}

myobj = {
   getlocalforagedata: (callback) => {
      var arr = [];
      localForage.keys().then((keys) => {
          keys.forEach((key) => {
              localForage.getItem(key).then(function (results) {
                  arr.push(results);
              });
          });
          callback && callback(arr);
      });
   }
}

Please help me break out of this madness.


Solution

  • The [previously] accepted answer to this question is using the explicit promise creation antipattern, a practice that makes code extra complicated and buggy.

    You can accomplish what you are trying to do far more cleanly, like this:

    function getLocalForageData() {
        return localForage.keys().then(function (keys) {
            return Promise.all(keys.map(function (key) {
                return localForage.getItem(key);
            });
        });
    }
    

    Example usage:

    getLocalForageData()
        .then(function (values) {
            console.log(values);
        })
        .catch(function (error) {
            console.error(error);
        });
    

    The above obtains an array of values, which are not matched up with their respective keys. If you would like the values paired with their keys, you can do this:

    function getLocalForageData() {
        return localForage.keys().then(function (keys) {
            return Promise.all(keys.map(function (key) {
                return localForage.getItem(key)
                    .then(function (value) {
                        return { key: key, value: value };
                    });
            }));
        });
    }
    

    Or you could break out one of the inner functions to reduce the nesting:

    function getLocalForageValueWithKey(key) {
        return localForage.getItem(key)
            .then(function (value) {
                return { key: key, value: value };
            });
    }
    
    function getLocalForageData() {
        return localForage.keys().then(function (keys) {
            return Promise.all(keys.map(getLocalForageValueWithKey));
        });
    }
    

    In either case, the code to call and use the getLocalForageData function would be the same as above.