Javascript 从标准for循环中的异步调用返回响应

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

在阅读了Felix Kling的文章之后,我仍然对如何从异步回调返回值感到困惑

我的目标是:将静态图像转换为base64一次,并将该图像存储在indexDB中,直到indexDB抛出某种存储错误

我正在使用这个异步npm模块

// 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');
  });
};