【问题标题】:Chain promises with localforage使用 localforage 链式承诺
【发布时间】:2017-11-13 05:33:16
【问题描述】:

我正在努力兑现承诺。我通过.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);
      });
   }
}

请帮助我摆脱这种疯狂。

【问题讨论】:

  • 不清楚,你想在你的函数中得到一个承诺,对吧?
  • 我想要的是让这个承诺返回一个对象。 (老实说,我希望不涉及承诺。我从不使用它们,因为我似乎无法掌握它们。但是,我正在使用 localForage 并且它使用它们。我想让 localForage 做这件事,我构建了一个要返回的对象)---希望有所帮助
  • 一个对象用于所有功能?
  • 是的,只有一个对象来自 localForage 的承诺。
  • localForage.getItem(key).then.. - LocalStorage.get 不返回 Promise

标签: javascript promise localforage


【解决方案1】:

[以前] 接受此问题的答案是使用 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 函数的代码都与上述相同。

【讨论】:

  • 哇!非常感谢。我会努力解决这个问题。我按照建议做了这些例子,除了丢失之外),它们工作得很好。哇哇哇。我有很多要学习的承诺。
  • @perl2go 我想我现在已经修复了丢失的括号。感谢您指出了这一点。一旦你掌握了它们的窍门,承诺就会很棒!
【解决方案2】:

[编辑] 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 的 Promise 示例: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

【讨论】:

  • 成功了!!!太感谢了。我会认真研究这个。非常感谢。
  • 不客气,promise 起初理解起来很奇怪,但最后非常有用
  • 但是getlocalforagedata应该是一个函数,而不是一个promise。
  • 发布的内容对我来说是“连接点”,我能够得到其余的。让这个数组脱离承诺是我的主要问题。
  • 我将准备一个简单的示例并发布我的结果。希望它可以帮助别人。
【解决方案3】:

问题中代码的一些功能不是必需的:

  • new Promise(...): localForage.keys() 返回一个构成 Promise 链根的 Promise。
  • callback通过从getlocalforagedata() 返回一个promise,调用者可以链接getlocalforagedata().then(...),避免需要传递回调。
  • Outer var arr一个正确构建的 Promise 链可以在没有任何外部变量的情况下收集和交付结果。

以下是必要的:

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

试试这个:

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(...)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多