2017-01-19 5 views
0

У меня есть способ получения/обновления состояния, хранящегося в PouchDB. Этот метод вызывается конструктором элемента для присвоения элемента уникальному уникальному тегу. Упрощенная версия кода выглядит так:Высокочастотные обновления для PouchDB (конфликт обновления документа)

var tagList = [ /* set of dictionary words to cycle through */ ]; 
function generateTag(id) { 
    return db.get('tags').then(function (tagData) { 
     var tag = '', remainder = tagData.tagCount, quotient; 

     while (remainder >= tagList.length) { 
      quotient = Math.floor(remainder/tagList.length); 
      tag += tagList[quotient - 1]; 
      remainder -= tagList.length * quotient; 
     } 
     tag += tagList[remainder]; 
     tag = tag.charAt(0).toLowerCase() + tag.slice(1); 

     tagData.tagCount++; 
     tagData.tags[tag] = id; 

     db.put(tagData); 
     return tag; 
    }).catch(function (err) { 
     console.error(err); 
    }); 
} 

class Element { 
    constructor() { 
     var self = this; 
     generateTag('element' + Date.now()).then(function (tag) { 
      self.tag = tag; 
     }); 
    } 
} 

Эта логика работает так, как ожидалось, когда между созданием элементов существует задержка. Но когда элементы создаются в быстром пакете (т. Е. Цикл for), вызов db.get для второго, третьего и последующих элементов вызывается перед выполнением операции db.put для завершения первого элемента, что приводит к сообщениям о конфликте «Обновление документа» для последовательных элементов. Сначала я думал, что разрешение конфликта PouchDB автоматически обработает это для меня, но я ошибся.

Возможно, я не понимаю, как правильно обращаться с такими случаями, или есть лучший способ написать это? Мне нужно, чтобы последовательные звонки db.get эффективно блокировались до тех пор, пока не закончится текущая db.put из предыдущей операции. Я думал, возможно, даже придерживаясь статической ссылки на обещание, соответствующее последней операции PouchDB на объекте «теги», так что вместо db.get('tags') я бы запустил tagsPromise.then(function() { return db.get('tags'); }), но я все еще новичок с обещаниями и не знаю, было бы желательным способом решения этой проблемы или если эта проблема является даже реальной проблемой или чем-то, что я наложил на себя, не придерживаясь лучшего подхода?

UPDATE: Похоже, изменение логики всегда возвращает обещание и всегда начинаются с «одиночками» обещанием вместо db.get('tags') в generateTag функции, как я уже не фиксирует проблему, все еще хотят, чтобы понять, есть ли лучший подход.

ответ

0

Для других заинтересованных, это, как я переписал выше логики, используя tagPromise подход я упоминал в обновлении (если есть лучший ответ от экспертов PouchDB, я признаю, что вместо этого):

var tagList = [ /* set of dictionary words to cycle through */ ]; 
var tagPromise = db.get('tags'); 
function generateTag(id, callback) { 
    tagPromise = tagPromise.then(function() { 
     return db.get('tags'); 
    }).then(function (tagData) { 
     var tag = '', remainder = tagData.tagCount, quotient; 

     while (remainder >= tagList.length) { 
      quotient = Math.floor(remainder/tagList.length); 
      tag += tagList[quotient - 1]; 
      remainder -= tagList.length * quotient; 
     } 
     tag += tagList[remainder]; 
     tag = tag.charAt(0).toLowerCase() + tag.slice(1); 

     tagData.tagCount++; 
     tagData.tags[tag] = id; 
     callback(tag); 

     return db.put(tagData); 
    }).catch(function (err) { 
     console.error(err); 
    }); 
} 

class Element { 
    constructor() { 
     var self = this; 
     generateTag('element' + Date.now(), function (tag) { 
      self.tag = tag; 
     }); 
    } 
} 
0

Мне трудно следовать тому, чего вы пытаетесь достичь. Не могли бы вы разместить документ тегов и примеры элементов и тегов?

На первый взгляд, получение и обновление одного документа «тегов» выглядит довольно вонючим, я думаю, что было бы разумнее использовать представление. Но для информированного ответа мне понадобится дополнительная информация, пожалуйста! Благодаря!