将未定义的方法承诺添加到稍后在 Promise.all() 中解析的数组

Add an undefined method promise to an array to be resolved later in Promise.all()

我想排队连接后执行的数据库调用。 DB 对象在连接时创建并存储为模块的成员。

数据库模块:

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(...)
}

如果在 db.connectLocal() 设置 db.localDb 之前调用 getDocs(),则会出现以下错误(或类似错误),因为尚未定义 db.localDb:

TypeError: Cannot read property 'then' of undefined

是否可以将一个未定义的方法,即 returns 一个承诺,添加到稍后在 Promise.all() 中解析的数组中?关于如何解决这个问题还有其他想法吗?

此外,我正在使用 Vue.js 和 PouchDB。

您可以在数据库模块中做出承诺,而不仅仅是 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(),returns一个承诺。

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

我解决了我的队列问题,但这根本不是我想要解决的问题。

我的第一个问题是 Promise.all() 延迟调用我的方法,直到它被调用,但它们在添加到数组时被调用。这导致了我在问题中提到的错误。所以我需要重新考虑如何使用可能尚不存在的方法填充队列。

解决方案是将对数组(队列)的调用添加为字符串(例如 "getDocs"),然后使用 bracket notation 遍历数组调用方法(例如 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();

这里有一个 fiddle,其中包含一个允许方法参数的示例:https://jsfiddle.net/rjbv0284/1/