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

Utilize mouseover to rotate the camera in three.js

Is it possible to utilize Three.js to rotate a camera and view an object from all angles upon hovering with the mouse? ...

ReactJS is giving me an error message: "Uncaught TypeError: Unable to access property 'ownerDocument' since it is null."

Trying to create a bar chart using D3 and render it with React's render method. Below is my index.js file: import React from 'react'; import ReactDOM from 'react-dom'; import './Styles/index.css'; import BarChart from &a ...

Tips for inserting items into an array of objects?

I have an array of objects with categories and corresponding points, and I need to calculate the total points for each category. { category: A, points:2 }, { category: A points: 3 }, { category: B, points: ...

Is there a way to manipulate text in JQuery without altering the inner element?

I am struggling with an issue in my HTML code. Currently, I have the following structure: <h3 id="price">0.00<sup id="category">N/A</sup></h3> My intention is to use AJAX to replace the content within the <h3 ...

What is the reason javascript struggles to locate and replace strings with spaces in a URL?

Let me begin by sharing the code I'm currently working on so that you can easily follow my explanations. Apologies for the French language used, as this website is being developed for a French-speaking school. I have eliminated irrelevant sections fro ...

HTML background image not displaying in JSPDF addHTML function

I am facing an issue with my HTML page where the background image in the header section is not displaying when converting the page to PDF using jspdf. Although all the other content appears correctly, the background image seems to be missing. You can vie ...

Can dynamic attributes be used with ternary operators in Angular?

I attempted to alter the id of a div using Angular and implemented the following code: <div [id]="'item_' + (itemName !== undefined ? itemName.replace(' ', '-').toLowerCase() : '')"> However, when I run my te ...

Enter key triggering input change event is unresponsive in Internet Explorer

$("#inputBoxWidth").change(function() { var curValue = $("#inputBoxWidth").val(); alert(curValue); }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <form> <input type="text" id="inputBo ...

Encountering a call stack size error when utilizing Vue-Resource within a Vuex store

I'm struggling to integrate an array from my api into a component using Vuex. The code I had when accessing the api directly from the component worked fine: data () { return { catalog:[], } }, created() { this.$http.get('https://example.net ...

When anchor is set programmatically, the focus outline is not displayed

I am currently facing an issue with my application where I am programmatically setting focus on elements in certain scenarios. While it generally works well, I have noticed that when I set the focus on an anchor element using $("#link1").focus(), the focus ...

Is there a way to automatically populate an AngularJS input field?

Attempting to automate filling out a website using JavaScript. The script below: document.getElementsByClassName('form-control')[1].value = "MYNAME"; The input text changes, but upon clicking the submit button it displays as empty. Any as ...

Stepping up Your Next.js Game with the Razorpay Payment Button Integration

When using the Razorpay payment button on a website, it provides a code snippet like this: <form> <script src = "https://cdn.razorpay.com/static/widget/payment-button.js" data-payment_button_id = "pl_FNmjTJSGXBYIfp" data ...

The code snippet for the React TypeScript Cheatsheet in the Portal sample appears to be malfunction

I have implemented a strict version of TypeScript and ESLint in my project. The code for this portal was originally sourced from the documentation available here: After making some modifications, the code now looks like this: import React, { useEffect, u ...

Any methods for integrating js.erb files in Ruby on Rails 7?

I've been searching for a while now on how to integrate js.erb files into my Ruby On Rails 7 project, but I haven't been able to find any helpful information. Have js.erb files become obsolete in Rails 7? If so, is there a way to include partials ...

Challenges encountered when using setState to assign values

Just started using React and running into an issue with updating state when changes are made to a Textfield. I'm working with a functional component where the initial state is set using useState. I feel like I might be overlooking something simple... ...

Fill in the select dropdown menu

I am trying to trigger the population of a select dropdown when the user clicks on it. The issue I am facing is that the click handler seems to be activated only when the user clicks on the options within the select, whereas in my case there are no optio ...

Creating a compact pivot grid using Vue.js without relying on any external libraries

Looking to create a simple and compact pivot grid in Vue, but all the available packages seem like an overkill for my needs. I only require two rows and four columns of data from a basic JSON object. If we consider the data to be structured as follows: [ ...

What is the best way to extract "true" values from an array and store them in a new array during iteration?

I am currently enrolled in a Codecademy course and I am facing a roadblock. My main goal is to gain a solid grasp of JavaScript. The current task at hand is as follows: "There is an array of unnecessary words. Your goal is to iterate over the array and fi ...

Run the js.erb code only when a certain condition is met

I'm feeling a bit lost when it comes to CoffeeScript and JS. I have a quick editing feature that sends an AJAX request and updates the database. Currently, I manually change the edited content's place and display it, but it feels like a workaroun ...

To prevent DOM errors in Vue-bootstrap and Nuxt.js, it is recommended to utilize the <b-dropdown> element within the <b-collapse> component

Here is the code I have for my navigation menu: <b-navbar toggleable="lg" class="navbar navbar-expand-lg navbar-light"> <b-navbar-toggle target="nav-collapse" class="mx-auto my-0"></b-navbar-toggle&g ...