嵌套承诺 - 使用 Dexie 的 IndexedDB 事务

Nested promises - IndexedDB transactions using Dexie

我有以下代码,其中基于内部承诺修改数据库项不起作用。

    $('input[type=checkbox][name=checklist]:checked').each(function()
    {
        var collection=db.items.where("name").equals(checkbox.val());
        var success;
        collection.modify(function(item){
             var invokePromise;
                //invokePromise = a fucntion that returns a promise 
                //this invokepromise function needs the item from the db.

             invokePromise.then(function(thirdPartyResponse){
                    item.date=new Date();
                    item.attempts= item.attempts+1; <-- this is not being updated.
            }).catch(function(error){
                    delete this.value; <-- this is also not deleted

            });
        }); 
    });

Collection.modify() 的回调必须同步更新项目。您还可以使用 anyOf() 而不是 equasls 来优化查询。下面是另一个策略的示例:

function yourAction () {
  const checkedValues = $('input[type=checkbox][name=checklist]:checked')
    .toArray() // Convert to a standard array of elements
    .map(checkBox => checkBox.value); // Convert to an array of checked values

  return invokePromise.then(thirdPartyResponse => {
    return db.items.where("name").anyOf(checkedValues).modify(item => {
      item.date = new Date();
      ++item.attempts;
    }).catch(error => {
      console.error("Failed to update indexedDB");
      throw error;
    });
  }).catch(error => {
    // Handle an errors from invokePromise
    // If an error occurs, delete the values. Was this your intent?
    console.error("Error occurred. Now deleting values instead", error);
    return db.items.where("name").anyOf(checkedValues).delete();
  });
}

正在考虑 @David Fahlander answer that Collection.modify() must synchronously update the item, you should collect the async responses first and after alter the database. You can use Promise.all() 异步收集来自 invokePromise 的响应,然后一次性修改数据库。

您可以检索所有条目,等待承诺,然后单独更新它们:

 (async function() {
   const entries = await db.items
       .where("name").equals(checkbox.val())
       .toArray();

   for(const entry of entries) {
     //...
     await invokePromise;
     await db.items.put(entry);
  }
})();

您可能希望将整个事情与 entries.mapPromise.all 以及 Table.putAll 并行化。