Implement a new method called "defer" to an array that will be resolved at a later time using Promise.all()

I need to manage a queue of DB calls that will be executed only once the connection is established. The DB object is created and stored as a member of the module upon connection.

DB Module:

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

Adding calls to the queue:

var dbQueue = []

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

// Will be called once connected and the queue is not empty:
function processQueue () {
  Promise.all (dbQueue)
  .then(...)
}

If getDocs() is invoked before db.connectLocal() sets db.localDb, then an error similar to the following may occur because db.localDb is not yet defined:

TypeError: Cannot read property 'then' of undefined

Is it possible to add an undefined method that returns a promise to an array for later resolution using Promise.all()? Any other suggestions on how I can tackle this problem?

Additionally, I am utilizing Vue.js and PouchDB in this scenario.

Answer №1

To ensure a more efficient code structure, consider implementing a promise within your database module rather than solely relying on the localDb property:

let localDatabase = null;
let resolveLocalDatabase = null;
let localDatabasePromise = new Promise(function(resolve, reject) {
    resolveLocalDatabase = resolve;
});

var dbModule = {
  getLocalDatabase: () {
    return localDatabasePromise;
  }
  establishLocalConnection: (databaseName) => {
    // Perform necessary operations
    localDatabase = new PouchDB(databaseName); // contains an allDocs() method
    resolveLocalDatabase(localDatabase);
  }
}

Subsequently, replace instances of .localDb with getLocalDatabase(), which will retrieve a promise.

dbQueue.push(
  dbModule.getLocalDatabase().then(db => db.allDocs())
)

Answer №2

I encountered a solution to my queue problem, and it was quite different from what I initially attempted.

The mistake I made was assuming that Promise.all() postpones the execution of my methods until called, but in reality, they are executed when added to the array. This led to the error mentioned earlier in my question. Therefore, I had to reconsider how to populate the queue with methods that may not be defined yet.

The workaround involved adding method calls as strings (e.g., "getDocs") to an array (the queue), then iterating through the array to invoke the methods using bracket notation (e.g., db["getDocs"]()).

Although my application is built with Vue.js, here is a basic, functional illustration:

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

// Queue for storing DB operations
var dbQueue = [];

// Processing the queue - triggered elsewhere after establishing a connection with the DB
// The processed array and Promise.all() may not be essential, but I prefer logging results sequentially
async function processQueue() {
  var processed = []; // Methods invoked from the queue

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

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

  // Clearing the queue
  dbQueue = [];
}

// Including some method calls in the queue even though the methods do not exist yet
dbQueue.push("getDocs");
dbQueue.push("getDocs");

// Simulating the addition of a method
db.getDocs = function() {
  return new Promise(resolve => {
    resolve(this.docs);
  });
};

// Executing the queue once the necessary conditions are met (such as connecting to the DB); triggered elsewhere
processQueue();

For those interested, here's a fiddle demonstrating an example allowing arguments for the methods: https://jsfiddle.net/rjbv0284/1/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Show or hide the expand/collapse button based on the height of the container

Looking for a way to hide content in a Div if it's taller than 68px and display an expand option? The challenge lies in detecting the height of the responsive Div, especially since character count varies. I attempted using PHP to count characters bu ...

What could be causing the issue when attempting to run "npm run serve"?

Can anyone help me understand this error message and suggest a possible solution? Failed to compile. ./src/main.js Module build failed (from ./node_modules/eslint-loader/index.js): Error: No ESLint configuration found. at Config.getLocalConfigHierar ...

Centered on the screen are the input field and corresponding label

I am in the process of creating a signup form, and I have encountered an issue. How can I make the input wider without using a fixed width like width: 420px? Additionally, I would like to center both the input field and the label. I envision something simi ...

ReactJS with conditional closing tags

Here is a sample json response : {id: 1, name: a} {id: 2, name: b} {id: 3, name: c} {id: 4, name: d} {id: 5, name: e} {id: 6, name: f} I am looking to organize these by pairs in my React component like so : <div className="group-item"> ...

The function Router.use is looking for a middleware function, but instead received an object in node.js /

I encountered an issue while trying to setup routing in my application. Whenever I attempt to initialize a route using app.use() from my routes directory, I receive an error stating that Router.use() requires a middleware function but received an Object in ...

Problems during the installation of Webpack

Encountering Error Setting up Webpack and Babel with NPM npm ERR! Unexpected end of JSON input while parsing near '...pdragon":"^0.7.0","to' npm ERR! A complete log of this run can be found in: npm ERR! A complete log of this run can be found ...

When using vue-router push, the first page should not be concealed even if the data array is extensive

After navigating from Home.vue to History.vue using this.$router.push("/history/" + fileid);, a socket.io request is triggered in the created or mounted lifecycle hook which fetches a large amount of data. The rendering process, especially with v-for, take ...

Error in Next.js: react-dom.development.js?ac89:14906 - Hook call is invalid. Hooks should only be used within a function component's body

Here is the code snippet I am working with: <div onClick={(e) => handleClick()}>Join Us</div> This is the handleClick function in my code: const handleClick = () => { console.log(Lang.getLocale()) }; And this is the Lang class metho ...

creating a distinct angular service for every controller

Lately, I've been utilizing Angular services to store my commonly used codes that are required across different parts of my project. However, I have encountered an issue where variables in the service are shared between controllers. This means that if ...

Browsing HTML Documents with the Click of a Button

After collecting JSON data from a SharePoint list, I am currently in the process of creating an HTML Document. At this point, I have completed approximately 80% of the expected outcome. Due to Cross-Origin Resource Sharing (CORS) restrictions, I have hard ...

What is the best way to animate specific table data within a table row using ng-animate?

Are you working with Angular's ng-repeat to display a table with multiple rows? Do you wish to add an animation effect to specific cells when a user hovers over a row in the table? In the scenario outlined below, the goal is to have only certain cell ...

Embedding a table inside a Bootstrap popover

I'm struggling with adding a table inside a Bootstrap popover. When I click on it, the table doesn't show up. This is my first time trying to insert HTML into a popover, so I don't know the correct way to do it. Any help would be appreciated ...

Exploring the seamless integration of the Material UI Link component alongside the Next.JS Link Component

Currently, I am integrating Material-UI with Next.js and would like to leverage the Material-UI Link component for its variant and other Material UI related API props. However, I also require the functionality of the Next.js Link component for navigating b ...

Struggling to pass command line arguments to index.ts with yarn?

My objective is to pass arguments through the command line using yarn start to index.ts. "scripts": { "start": "tsc-watch --onSuccess \"ts-node --pretty -r tsconfig-paths/register' src/index.ts\"", } When I attempt something like: yarn ...

Having trouble with the filtering feature in Material UI Datagrid

I'm currently using Material UI Data Grid to display a table on my website. The grid has an additional filter for each column, but when I click on the filter, it hides behind my Bootstrap Modal. Is there a way to bring it to the front? https://i.stac ...

Can two Angular element components be utilized simultaneously on a single page in Angular 6?

Currently, I'm attempting to host independent Angular elements that can be seamlessly integrated into a non-Angular webpage. Everything works perfectly fine when there's only one element on the page, but as soon as I try to load two or more, I en ...

increasing the efficiency of exporting large amounts of data in Laravel to prevent timeout errors

I need to create a monthly report based on a database containing thousands of records. Sometimes, users may request reports spanning multiple months. With the current record size, a month's worth of data can exceed 5000 entries. Currently, I am utili ...

Changing the CSS property from "display: none" to "display: block" using JavaScript causes all the div elements to overlap

My issue involves several radio inputs where clicking one should reveal a hidden div containing information. However, when this div appears, it overlaps with the footer instead of staying positioned between the footer and radio input as intended. I am str ...

Using Node.js to display the outcome of an SQL query

I have been attempting to execute a select query from the database and display the results. However, although I can see the result in the console, it does not appear on the index page as expected. Additionally, there seems to be an issue with the way the r ...

Display radio buttons depending on the selections made in the dropdown menu

I currently have a select box that displays another select box when the options change. Everything is working fine, but I would like to replace the second select box with radio buttons instead. Can anyone assist me with this? .sub{display:none;} <sc ...