Javascript 从标准for循环中的异步调用返回响应
在阅读了Felix Kling的文章之后,我仍然对如何从异步回调返回值感到困惑 我的目标是:将静态图像转换为base64一次,并将该图像存储在indexDB中,直到indexDB抛出某种存储错误 我正在使用这个异步npm模块Javascript 从标准for循环中的异步调用返回响应,javascript,asynchronous,callback,indexeddb,Javascript,Asynchronous,Callback,Indexeddb,在阅读了Felix Kling的文章之后,我仍然对如何从异步回调返回值感到困惑 我的目标是:将静态图像转换为base64一次,并将该图像存储在indexDB中,直到indexDB抛出某种存储错误 我正在使用这个异步npm模块 // init the idb store const initIDB = async () => { const db = await openDB('db', 1, { upgrade(db) { db.createObjectStore
// init the idb store
const initIDB = async () => {
const db = await openDB('db', 1, {
upgrade(db) {
db.createObjectStore('tempStore', { keyPath: 'id', autoIncrement: true });
},
});
const tx = db.transaction('tempStore', 'readwrite');
await overloadIDB(tx.store);
await tx.done;
return true;
};
理想情况下,我希望从toDataURL的
回调函数返回值,并在for循环中使用该结果,但由于异步行为,我总是得到未定义的
上述代码多次无法执行事务store.add(data)
,并且在i=0
时失败
我试着用一个新的承诺(解析、拒绝)将toDataURL
包装起来,就像这样
const toDataURL = (url, callback) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = () => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(callback(reader.result));
};
reader.readAsDataURL(xhr.response);
};
xhr.send();
});
然后使用Promise.all
解析这样的存储数组
const overloadIDB = async (store) => {
const imgurl = 'someLocalImage.png';
const promises = [];
return toDataURL(imgurl, async (s) => {
console.log('s :', s);
for (let i = 0; i < 10; i++) {
if (i > 0 && i % 100 === 0) console.log('A set done');
try {
const num = Math.round(getRandomArbitrary(1, 1000000));
const data = {
id: num,
img: s,
};
promises.push(store.add(data));
} catch (e) {
console.log(e.toString());
console.dir(e);
break;
}
}
await Promise.all(promises);
console.log('Done');
});
};
常量重载IDB=async(存储)=>{
const imgurl='someLocalImage.png';
常量承诺=[];
返回到数据URL(imgurl,异步)=>{
console.log('s:',s);
for(设i=0;i<10;i++){
如果(i>0&&i%100==0)console.log('A set done');
试一试{
const num=Math.round(getrandomArbital(110000));
常数数据={
id:num,
img:s,
};
promises.push(存储.添加(数据));
}捕获(e){
log(例如toString());
署长(e);
打破
}
}
等待承诺。所有(承诺);
console.log('Done');
});
};
但返回一个错误未能在“IDBObjectStore”上执行“add”:事务已完成。
在这一点上,我认为我的方法是有缺陷的,但我不确定如何修复它。有人能指出一些解决方案吗?< /P> < P>你不能在索引XDB操作的中间执行异步操作。完全执行提取,然后连接、创建事务并存储结果。IDB如何获取存储?听起来商店是你的问题;当您尝试进行新交易时,它已关闭该交易。它是在第一次通过for循环还是在第二次循环时这样做的?store.add是否返回承诺?该存储作为参数传递给IDB。我相信它是第一次关闭事务,因为
I
从未递增。是的,store.add返回一个承诺
const toDataURL = (url, callback) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = () => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(callback(reader.result));
};
reader.readAsDataURL(xhr.response);
};
xhr.send();
});
const overloadIDB = async (store) => {
const imgurl = 'someLocalImage.png';
const promises = [];
return toDataURL(imgurl, async (s) => {
console.log('s :', s);
for (let i = 0; i < 10; i++) {
if (i > 0 && i % 100 === 0) console.log('A set done');
try {
const num = Math.round(getRandomArbitrary(1, 1000000));
const data = {
id: num,
img: s,
};
promises.push(store.add(data));
} catch (e) {
console.log(e.toString());
console.dir(e);
break;
}
}
await Promise.all(promises);
console.log('Done');
});
};