我正在努力应对承诺。我看到事件链是如何通过.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);
});
}
}
请帮助我摆脱这种疯狂。
答案 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
})
注意:
更多强>
使用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(...)
。