连锁承诺与localforage

时间:2017-11-10 17:30:57

标签: javascript promise localforage

我正在努力应对承诺。我看到事件链是如何通过.then().then().then().then().then().then().then().then().then().then().then().then()发生的,但我无法弄清楚如何使它结束。我希望我能做一个简单的事情:

 .then(callback(mydata))

然而,我无法让它发挥作用。我正在努力实现这一目标。

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);
      });
   }
}

请帮助我摆脱这种疯狂。

3 个答案:

答案 0 :(得分:3)

这个问题的[之前]接受的答案是使用explicit promise creation antipattern,这种做法使代码更加复杂和错误。

你可以更干净地完成你想要做的事情,比如:

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

使用示例:

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

以上获取的值数组与其各自的键不匹配。如果您希望将值与其键配对,则可以执行以下操作:

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 };
                });
        }));
    });
}

或者你可以打破其中一个内部函数来减少嵌套:

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));
    });
}

在任何一种情况下,调用和使用getLocalForageData函数的代码都与上面相同。

答案 1 :(得分:1)

[编辑] JLRishe's answer并不错,但它会返回一个对于下次使用几乎无法读取的对象数组(您需要一个循环来获取值),以及似乎也忘记了null值,因此完整和欺骗解决方案应该更像:

  const getLocalForageDataByKeys = () => {
    return localForage.keys().then(keys => {
      return Promise.all(keys.map(key => {
        return localForage.getItem(key)
          .then(value => {
            return { [key]: value }
          })
          .catch(error => {
            console.log(error)
            return { [key]: null }
          })
      })).then(arr => {
        return Object.assign(...arr)
      })
    })
  }

<强>用法:

getLocalForageDataByKeys()
  .then(obj => {
    console.log(obj) // { keyA: 'valueA', keyB: 'valueB' }
  }).catch(error => {
    console.log(error) // do sth with error
  })

注意:

更好的是,此解决方案使用ES6jsLint最高质量标准

更多

使用localForage承诺示例:https://localforage.github.io/localForage/#data-api-getitem

使用承诺:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

使用对象分配:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

使用点差运算符:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

答案 2 :(得分:0)

问题中代码的几个特征是不必要的:

  • new Promise(...) localForage.keys()返回构成承诺链根目录的承诺。
  • callback :通过从getlocalforagedata()返回承诺,调用者可以链接getlocalforagedata().then(...),无需传递回调。
  • 外部变种arr正确构建的承诺链可以在没有任何外部变量的情况下收集和传递结果。

以下是必要的:

  • 汇总localForage.getItem(key)返回的承诺,并从链中的该步骤返回承诺。
  • 在等待if (err.length > 0)承诺解决的进一步链接if (arr.length > 0)中执行测试.then()localForage.getItem(key)

试试这个:

myobj = {
    getlocalforagedata: () => {
        return localForage.keys()
        .then(keys => {
            // Use `keys.map(...)` to return an array of promises.
            // Then use `Promsie.all()` to aggregate the promises returned by `localForage.getItem(key)`.
            return Promise.all(keys.map(key => localForage.getItem(key)));
        })
        .then(arr => { // an array of results
            // These tests must be performed in a chained `then()`,
            // which will wait for all the individual `localForage.getItem(key)` results (or errors) to be delivered
            if (arr.length > 0) {
                return arr; // deliver a non-empty array
            } else {
                throw new Error('no results'); // throw error down the promise chain's error path.
            }
        });
    }
}

请致电如下:

myobj.getlocalforagedata()
.then((results) => {
    // Work with results
})
.catch((error) => {
    // Do whatever with error.
    // Either return some default value or re-throw `error`
});
可以使

getlocalforagedata()使用回调,但更好的做法是返回一个承诺并允许调用者链接getlocalforagedata().then(...)