Вложенные обещания - транзакции IndexedDB с использованием Dexie - PullRequest
0 голосов
/ 24 января 2019

У меня есть следующий код, где изменение базы данных базы данных на внутреннем обещании не работает.

    $('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

            });
        }); 
    });

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

Учитывая @ David Fahlander ответ, что Collection.modify() должен синхронно обновлять элемент, вы должны сначала собрать асинхронные ответы, а затем изменить базу данных.Вы можете использовать Promise.all () для асинхронного сбора ответов от invokePromise и изменения базы данных за один раз.

0 голосов
/ 03 февраля 2019

Вы можете получить все записи, дождаться обещаний и затем обновить их отдельно:

 (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.map и Promise.all и Table.putAll.

0 голосов
/ 24 января 2019

Обратный вызов, данный 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();
  });
}
...