我正在尝试从异步函数返回一个自定义对象,该异步函数用作使用indexdb的put的包装器。
使用Promise很容易。 但是,使用异步/等待变得更具挑战性……
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);
}
}
想法是返回一个组合对象...但是由于返回成功后成功运行,我的所有尝试都失败了。
我在Google上搜索了很多,却找不到适当的方法来等待成功/错误事件。
我知道返回Promise更容易,因为resolve(result)最终会返回我想要的东西...但是我正在尝试学习使用async / await编写相同的代码。< / p>
非常感谢您
答案 0 :(得分:0)
我目前无法确认,但我认为应该是<!-- checkbox -->
<template>
<div class="checkbox-part">
<input class="checkbox-part-input" type="checkbox"
:name="name"
:id="id"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
<label class="checkbox-part-label"
:for="name"
:class="{ 'checkbox-part-label--checked': checked }"
>
<slot name="label"></slot>
</label>
<!-- removed for brevity -->
</div>
</template>
<script>
export default {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: {
type: Boolean,
},
name: {
type: String,
required: true
},
id: {
type: String,
required: true
}
}
}
</script>
<!--- parent component using the one -->
<template>
<!-- removed for brevity -->
<!-- ... -->
<div class="expandable-category-part-social-section">
<checkbox-part
v-model="isSocialIntegrationEnabled"
:id="title + 'social-media'"
:name="title + 'social-media'"
>
<template slot="label">
<div class="checkbox-part-label-text">Final text comes here...</div>
</template>
</checkbox-part>
</div>
<!-- ... -->
</template>
而不是await tx.complete
。
但是,即使API不直接支持Promises,仍然可行的通用解决方案是将await r.transaction.complete;
包裹在new Promise
和onsuccess
周围,并使用onerror
等待该Promise解决,然后在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);
}
}
答案 1 :(得分:0)
尝试一下:
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);
}
编辑,因为您坚持对set函数使用异步限定符,所以可以这样做。请注意,我觉得这很傻:
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);
}
答案 2 :(得分:0)
最终,您最终将把IDB封装在一个promise-friend库中,但是对于您的特定需求,您可以使用以下方法:
function promiseForTransaction(tx) {
return new Promise((resolve, reject) => {
tx.oncomplete = e => resolve();
tx.onabort = e => reject(tx.error);
});
}
然后在代码中,您可以编写以下内容:
await promiseForTransaction(r.tx);
...,它将等待事务完成,如果中止则抛出异常。 (请注意,这需要致电帮助程序 在交易可能已经完成/中止之前,因为 如果事件已经触发,它将永远无法解决)