javascript 在Firestore事务中执行提取请求:收到“无法修改已提交的WriteBatch”

ctehm74n  于 2022-11-27  发布在  Java
关注(0)|答案(1)|浏览(103)

我尝试在事务中执行提取请求,但在代码执行时收到以下错误。
错误:无法修改已提交的WriteBatch。
该函数执行的步骤如下:
1.计算文档引用(取自外部源)
1.查询Firestore中可用的文档
1.验证文档是否存在
1.获取更多详细信息(延迟加载机制)
1.开始填充第一级集合
1.开始填充第二级集合
在我使用的代码下面。

await firestore.runTransaction(async (transaction) => {

  // 1. Compute document references
  const docRefs = computeDocRefs(colName, itemsDict);
  // 2. Query the documents available in Firestore
  const snapshots = await transaction.getAll(...docRefs);
  snapshots.forEach(async (snapshot) => {
    // 3. Verify if document exists
    if (!snapshot.exists) {
      console.log(snapshot.id + " does not exists");

      const item = itemsDict[snapshot.id];
      if (item) {
        // 4. Fetch for further details
        const response = await fetchData(item.detailUrl);
        const detailItemsDict = prepareDetailPageData(response);

        // 5. Start populating first level collection
        transaction.set(snapshot.ref, {
          index: item.index,
          detailUrl: item.detailUrl,
          title: item.title,
        });

        // 6. Start populating second level collection
        const subColRef = colRef.doc(snapshot.id).collection(subColName);
        detailItemsDict.detailItems.forEach((detailItem) => {
          const subColDocRef = subColRef.doc();

          transaction.set(subColDocRef, {
            title: detailItem.title,
            pdfUrl: detailItem.pdfUrl,
          });
        });
      }
    } else {
      console.log(snapshot.id + " exists");
    }
  });
});

computeDocRefs的描述如下

function computeDocRefs(colName, itemsDict) {
  const identifiers = Object.keys(itemsDict);
  const docRefs = identifiers.map((identifier) => {
    const docId = `${colName}/${identifier}`
    return firestore.doc(docId);
  });
  return docRefs;
}

fetchData则使用了axios

async function fetchData(url) {
  const response = await axios(url);
  if (response.status !== 200) {
    throw new Error('Fetched data failed!');
  }
  return response;
}

prepareMainPageDataprepareDetailPageData是准备将它们归一化的数据的函数。
如果我注解await fetchData(item.detailUrl),则第一级集合及其关联的所有文档都将正确存储。
相反,对于await fetchData(item.detailUrl),错误发生在以下注解中:// 5. Start populating first level collection .
操作的顺序很重要,因为如果不需要,我现在确实想进行第二次调用。
你能引导我找到正确的解决方案吗?

drnojrws

drnojrws1#

此问题是由于forEachasync/await不能很好地协同工作。例如:Using async/await with a forEach loop
现在我完全改变了我所遵循的方法,现在它工作得很顺利。
现在的代码如下所示:

// Read transaction to retrieve the items that are not yet available in Firestore
const itemsToFetch = await readItemsToFetch(itemsDict, colName);
// Merge the items previously retrieved to grab additional details through fetch network calls
const fetchedItems = await aggregateItemsToFetch(itemsToFetch);
// Write transaction (Batched Write) to save items into Firestore
const result = await writeFetchedItems(fetchedItems, colName, subColName);

非常感谢道格史蒂文森和雷诺·塔内克。

相关问题