Добавить неопределенное обещание метода в массив, который будет разрешен позже в Promise.all () - PullRequest
0 голосов
/ 30 января 2019

Я хочу поставить в очередь вызовы БД, которые будут выполняться после подключения.Объект БД создается и сохраняется как член модуля при подключении.

Модуль БД:

var db = {
  localDb: null,
  connectLocal: (dbName) => {
    // Do stuff
    this.localDb = new PouchDB(dbName) // has a allDocs() method
  }
}

Добавление вызовов в очередь:

var dbQueue = []

function getDocs () {
  dbQueue.push (
    db.localDb.allDocs () // allDocs() not yet defined; returns promise
  )
}

// Called when connected and queue is not empty:
function processQueue () {
  Promise.all (dbQueue)
  .then(...)
}

ЕслиgetDocs () вызывается до того, как db.connectLocal () устанавливает db.localDb, затем я получаю следующую ошибку (или похожую), потому что db.localDb еще не определено:

TypeError: Cannot read property 'then 'of undefined

Возможно ли добавить неопределенный метод, который возвращает обещание, в массив, который будет разрешен позже в Promise.all ()?Любые другие идеи относительно того, как я могу решить эту проблему?

Также я использую Vue.js и PouchDB.

Ответы [ 2 ]

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

Я решил проблему с очередью, но я совсем не пытался ее решить.

Моей первой проблемой было то, что Promise.all () откладывал вызов моих методов до тех пор, пока он не был вызван., но они вызываются при добавлении в массив.Это вызвало ошибку, о которой я упоминал в своем вопросе.Поэтому мне нужно было переосмыслить, как заполнять очередь методами, которые еще не существуют.

Решением было добавить вызовы в массив (очередь) в виде строк (например, "getDocs"), а затем выполнить циклмассив, вызывающий методы с использованием обозначения в скобках (например, db["getDocs"]()).

Мое приложение написано на Vue.js, поэтому оно явно отличается, но вот упрощенный рабочий пример:

// Dummy DB object
var db = {
  docs: [1, 2, 3]
};

// Queue were the DB ops are stored
var dbQueue = [];

// Process the queue - called elsewhere once the DB is connected
// The processed array and Promise.all() aren't necessary as you could just call
// the method outright, but I want to log the results in order
async function processQueue() {
  var processed = []; // Called queue methods

  // Add valid methods to
  dbQueue.forEach(method => {
    if (typeof db[method] === "function") {
      return processed.push(db[method]());
    } else {
      console.error(`"${method}" is not a name of a valid method.`);
    }
  });

    // Log promise results
  await Promise.all(processed).then(res => {
    console.log("Processed:", res);
  });

  // Empty the queue
  dbQueue = [];
}

// Add some calls to the queue of methods that don't yet exist
dbQueue.push("getDocs");
dbQueue.push("getDocs");

// Simulate adding the method
db.getDocs = function() {
  return new Promise(resolve => {
    resolve(this.docs);
  });
};

// Process queue once conditions are met (e.g. db is connected); called elsewhere
processQueue();

А вот скрипка с примером, который допускает аргументы для методов: https://jsfiddle.net/rjbv0284/1/

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

Вы можете сделать обещание в своем модуле БД вместо свойства localDb:

let localDb = null;
let resolveLocalDb = null;
let localDbPromise = new Promise(function(resolve, reject) {
    resolveLocalDb = resolve;
});

var db = {
  getLocalDb: () {
    return localDbPromise;
  }
  connectLocal: (dbName) => {
    // Do stuff
    localDb = new PouchDB(dbName) // has a allDocs() method
    resolveLocalDb(localDb);
  }
}

Затем обменяйте .localDb на getLocalDb(), что возвращает обещание.

dbQueue.push(
  db.getLocalDb().then(db => db.allDocs())
)
...