[英]await for indexdb event in async function
I'm trying to return a custom object from a async function that works as wrapper for a put using indexdb. 我试图从异步函数返回一个自定义对象,该异步函数用作使用indexdb的put的包装器。
Using Promises this is easy. 使用Promises,这很容易。 However, using async/await became more challenging... 但是,使用异步/等待变得更具挑战性...
const set = async (storeName, key, value) => {
if (!db)
throw new Error("no db!");
try {
const result = {};
let tx = db.transaction(storeName, "readwrite");
let store = tx.objectStore(storeName);
let r = store.put({ data: key, value: value });
console.log(r);
r.onsuccess = async () => {
console.log('onsuccess');
result.something = true;
}
r.onerror = async () => {
console.log('onerror');
result.something = false;
}
await r.transaction.complete; // ok... this don't work
// how can I await until onsuccess or onerror runs?
return result;
} catch (error) {
console.log(error);
}
}
The ideia is to return a composed object... however all my attemps fails as onsuccess runs after returning the result. 想法是返回一个组合对象……但是由于返回成功后成功运行,我的所有尝试都失败了。
I googled a lot and could't find a way to proper await for onsuccess/onerror events. 我在Google上搜索了很多,却找不到适当的方法来等待成功/错误事件。
I know that returning a Promise is more easy as resolve(result) would end returning what I want... but i'm trying to learn to make same code using async/await . 我知道返回Promise更容易,因为resolve(result)最终将返回我想要的东西……但是我正在尝试学习使用async / await编写相同的代码 。
Thank you so much, 非常感谢,
I can't confirm it right now but I think it should be await tx.complete
instead of await r.transaction.complete;
我目前无法确认,但是我认为应该await tx.complete
而不是await r.transaction.complete;
. 。
But a general solution that would work even if the API would not support Promises directly would be to wrap a new Promise
around the onsuccess
and onerror
and use await
to wait for that Promise to resolve, and in your onsuccess
and onerror
you then call the resolve
function: 但是,即使API不支持的承诺,将工作的通用解决方案,直接将包装一个new Promise
周围onsuccess
和onerror
和使用await
,等待这个承诺来解决,并在你onsuccess
和onerror
,你再调用resolve
功能:
const set = async (storeName, key, value) => {
if (!db)
throw new Error("no db!");
try {
const result = {};
let tx = db.transaction(storeName, "readwrite");
let store = tx.objectStore(storeName);
let r = store.put({
data: key,
value: value
});
console.log(r);
await new Promise((resolve, reject) => {
r.onsuccess = () => {
console.log('onsuccess');
result.something = true;
resolve()
}
r.onerror = () => {
console.log('onerror');
result.something = false;
// I assume you want to resolve the promise even if you get an error
resolve()
}
})
return result;
} catch (error) {
console.log(error);
}
}
I would furhter change it to: 我会进一步将其更改为:
try {
await new Promise((resolve, reject) => {
r.onsuccess = resolve
r.onerror = reject
})
console.log('success');
result.something = true;
} catch(err) {
console.log('error');
result.something = false;
}
Try this: 尝试这个:
function set(db, storeName, key, value) {
return new Promise((resolve, reject) => {
let result;
const tx = db.transaction(storeName, 'readwrite');
tx.oncomplete = _ => resolve(result);
tx.onerror = event => reject(event.target.error);
const store = tx.objectStore(storeName);
const request = store.put({data: key, value: value});
request.onsuccess = _ => result = request.result;
});
}
async function callIt() {
const db = ...;
const result = await set(db, storeName, key, value);
console.log(result);
}
Edit, since you insist on using the async qualifier for the set function, you can do this instead. 编辑,因为您坚持对set函数使用异步限定符,所以可以改为执行此操作。 Please note I find this pretty silly: 请注意,我觉得这很愚蠢:
async function set(db, storeName, key, value) {
// Wrap the code that uses indexedDB in a promise because that is
// the only way to use indexedDB together with promises and
// async/await syntax. Note this syntax is much less preferred than
// using the promise-returning function pattern I used in the previous
// section of this answer.
const promise = new Promise((resolve, reject) => {
let result;
const tx = db.transaction(storeName, 'readwrite');
tx.oncomplete = _ => resolve(result);
tx.onerror = event => reject(event.target.error);
const store = tx.objectStore(storeName);
const request = store.put({data: key, value: value});
request.onsuccess = _ => result = request.result;
});
// We have executed the promise, but have not awaited it yet. So now we
// await it. We can use try/catch here too, if we want, because the
// await will translate the promise rejection into an exception. Of course,
// this is also rather silly because we are doing the same thing as just
// allowing an uncaught exception to exit the function early.
let result;
try {
result = await promise;
} catch(error) {
console.log(error);
return;
}
// Now do something with the result
console.debug('The result is', result);
}
Ultimately you'll end up wrapping IDB in a promise-friend library, but for your specific need, you could use something like this: 最终,您最终将把IDB封装在一个promise-friend库中,但是对于您的特定需求,您可以使用以下方法:
function promiseForTransaction(tx) {
return new Promise((resolve, reject) => {
tx.oncomplete = e => resolve();
tx.onabort = e => reject(tx.error);
});
}
And then in your code you can write things such as: 然后,您可以在代码中编写以下内容:
await promiseForTransaction(r.tx);
... which will wait until the transaction completes, and throw an exception if it aborts. ...,它将等待事务完成,如果中止则抛出异常。 (Note that this requires calling the helper before the transaction could possibly have completed/aborted, since it won't ever resolve if the events have already fired) (请注意,这需要在事务可能完成/中止之前调用帮助程序,因为如果事件已经触发,它将永远无法解决)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.