在从查找

时间:2017-12-07 16:18:03

标签: javascript node.js mongodb asynchronous

我想要一个管理mongodb集合的store js对象,其行为如下:

store.insert(thing); // called from a pubsub system that don't wait the insert to finish

store.get(); // returns a promise that resolves to the things in the collection
// even if called immediately after insert it must contain the last thing inserted

我手动实现了它:

let inserts = 0;
let afterInserts = [];

const checkInsertsFinished = () => {
  if (inserts === 0) {
    afterInserts.forEach(resolve => resolve());
    afterInserts = [];
  }
};

const decrementInserts = () => {
  inserts -= 1;
  checkInsertsFinished();
};

const insertsFinished = () =>
  new Promise((resolve) => {
    afterInserts.push(resolve);
    checkInsertsFinished();
  });

const insert = (thing) => {
  inserts += 1;
  db.collection('mycollection').insertOne(thing).then(decrementInserts);
};

const get = async () => {
  await insertsFinished(); // if there are inserts happening, wait for them to finish
  return db.collection('mycollection').find({}).toArray();
};

return { insert, get };

我认为有更多的标准方法可以实现这一目标,但我错过了查找库或内置功能的词汇......你会怎么做?

感谢您的建议。

1 个答案:

答案 0 :(得分:0)

JavaScript是单线程的,您编写的代码都不能在多个线程上同时运行,因此您应该能够这样做:

let inserting = Promise.resolve(),
startGetting={};

const insert = (thing) => {
  startGetting={};//de-reference startGetting
  inserting = db.collection('mycollection').insertOne(thing)
  return inserting;
};

const get = () => {
  const rec = () =>
    inserting.then(
      _ =>
        new Promise(
          (resolve,reject)=>{
            //the next op is truely async (although I wonder why no promise),
            //  someone can insert while this is completing
            const start=startGetting;
            db.collection('mycollection').find({}).toArray(
              (err,results)=>
                err
                  ? reject(err)
                  //inserting could have been set to tby the time
                  //  this completed (in theory) so use startGetting reference equality
                  : startGetting === start
                    ? resolve(results)//while getting nobody inserted
                    : resolve(rec())
          )
        })
    );
  return rec();
};

return { insert, get };