Utilizing Promise and setTimeout in a generator function to develop an asynchronous generator: A comprehensive guide

I am currently working on creating a generator function that produces an async generator. This Generator will yield a deferred value at each time, using promises. The values and their respective delays (in milliseconds) are sourced from two separate arrays.

For the provided example code, the expected output is a sequential logging of each value from the target array along with its corresponding (matching index) delay from the timeArray. Each value should be logged one after the other, waiting for the specified delay, until the end of the iteration through the target array.

I attempted to run the code below, however it only displays the first 2 elements in the timeArray and does not log all the subsequent elements. I am uncertain if it prints them after the first two time intervals specified in the timeArray.

let j = 0;

// Array representing the delay before printing each number.
var timeArray = [6, 68, 51, 41, 94, 65, 47, 85, 76, 136];

// Array containing the numbers to be printed.
var targets = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7];

let generator = generateSequence();

async function* generateSequence(casiInfluence) {
  yield new Promise((resolve, reject) => {
    setTimeout(() => resolve(console.log(targetArray[j]), timeArray[j]); console.log(timeArray[j]);
  });
}
(async function main() {
  for await (var result of generateSequence()) {
    console.log(result);
    j++;
    result = generator.next();
  }
}());

Answer №1

You initiated the generator using

let generator = generateSequence()
, however, you did not proceed to iterate through its values.

(To enhance readability with more descriptive variable names, the code is as follows):

var timeArray = [6, 68, 51, 41, 94, 65, 47, 85, 76, 136];// An array indicating the delay before printing each number
var targets = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7];// An array of numbers to be printed

var generator = generateSequence();

( async () => {

    for await ( const printNumber of generator ) {
        /* No action needed in this loop as accessing the generator's properties logs data */
    }

} )()

async function* generateSequence() {
    for ( const i in timeArray ) {
        const delay = timeArray[ i ];
        const numberToPrint = targets[ i ];
        await waitForPrint( numberToPrint, delay );
        yield;
    }
}

function waitForPrint( text, delay ) {
    return new Promise( (resolve,reject) => {
        setTimeout(
            () => {
                console.log( text );
                resolve();
            },
            delay
        )
    })
}

A generator-free alternative:


var timeArray = [6, 68, 51, 41, 94, 65, 47, 85, 76, 136];// Array showing the delay before printing each number
var targets = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7];// Numbers to be printed


for( let scheduledTimeMS=0, i=0; i<timeArray.length; i++ ) {

    const numberToPrint = targets[ i ];
    const delay = timeArray[ i ];

    scheduledTimeMS += delay;

    setTimeout( () => console.log( numberToPrint ), scheduledTimeMS );

}

Answer №2

When moving towards developing a generator for deferred values, the OP could undertake several steps such as:

  • Converting both arrays of the OP into a more manageable data structure like an array of tuples where each tuple consists of [<value>, <delay>].

  • Transforming each value-delay tuple into a deferred value action through an async function that generates and returns a promise. This promise will resolve the value after a specific delay provided in delay. The function used to create this async function is called createDeferredValue.

  • Generating an async generator from the array of async functions with the help of a function named createPoolOfDeferredValues.

// - a specific helper which creates an async function
//   (encapsulating a promise) for each to be deferred value.
function createDeferredValue(value, delay) {
  return async function () {
    return await (
      new Promise(resolve => setTimeout(resolve, delay, value))
    );
  };
}

// - another helper which creates an async generator
//   from an array of async functions.
async function* createPoolOfDeferredValues(deferredValueList) {
  const asyncFunctions = [...deferredValueList];

  let asyncFct;
  while (asyncFct = asyncFunctions.shift()) {

    yield (await asyncFct());
  }
}


// - array that defines how long after each to be
//   processed value the next value will be processed.
const valueDelays = [600, 680, 510, 410, 940, 650, 470, 850, 760, 1360];

// - array of to be processed target values.
const targetValues = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7]


// - maps both above OP's arrays into a
//   better processable data-structure.
const targetEntries = targetValues
  .map((value, idx) => [value, valueDelays[idx]]);

console.log({ targetEntries });

// - helper task which creates a list of async functions.
const deferredValueList = targetEntries
  .map(([value, delay]) =>
    createDeferredValue(value, delay)
  );

// create an async generator ...
const poolOfDeferredValues =
  createPoolOfDeferredValues(deferredValueList);

(async () => {
  // ... and iterate over it.
  for await (const value of poolOfDeferredValues) {
    console.log({ value });
  }
})();

console.log('... running ...');
.as-console-wrapper { min-height: 100%!important; top: 0; }

However, once the list/array of async functions is created, it is possible to directly iterate over it using for...await without the need for an async generator. Therefore, the code can be simplified as follows:

// - a specific helper which creates an async function
//   (encapsulating a promise) for each to be deferred value.
function createDeferredValue(value, delay) {
  return async function () {
    return await (
      new Promise(resolve => setTimeout(resolve, delay, value))
    );
  };
}

// - array that defines how long after each to be
//   processed value the next value will be processed.
const valueDelays = [600, 680, 510, 410, 940, 650, 470, 850, 760, 1360];

// - array of to be processed target values.
const targetValues = [9, 10, 8, 7, 9, 7, 7, 9, 9, 7]


// - maps both above OP's arrays into a
//   better processable data-structure.
const targetEntries = targetValues
  .map((value, idx) => [value, valueDelays[idx]]);

console.log({ targetEntries });

// - helper task which creates a list of async functions.
const deferredValueList = targetEntries
  .map(([value, delay]) =>
    createDeferredValue(value, delay)
  );

(async () => {
  // - iterate the list of async functions by `for...await`.
  for await (const deferredValue of deferredValueList) {
    const value = await deferredValue();
    console.log({ value });
  }
})();

console.log('... running ...');
.as-console-wrapper { min-height: 100%!important; top: 0; }

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

Having trouble with the anchor tag not functioning properly

I'm looking to create a unique video experience by having an iframe video play automatically and opening a third-party video player in a lightbox style when clicked. Currently, the video autoplays, but I want it so that when the user clicks on the vi ...

Using Props with jQuery in React Components: A Comprehensive Guide

I trust you comprehend this straightforward example. I attempted to modify the background color of my HTML element during initial rendering by managing it in a React Component with a touch of jQuery assistance. Here is the code within my React Component ...

Obtain Data for Visualizing Graph with JSON within a Database-connected Graph (highchart.js)

In the process of creating a database-driven graph, I am utilizing libraries from Codepen. These libraries include: THIS and Highchart.js The HTML file on display simply showcases the chart, while the main data processing is handled in an index.js file t ...

Obtain the accurate sequence of tr elements in the form of a jQuery object

Even though you can define tfoot before tbody in the source code, when displayed in the browser tfoot will still appear last: <table> <thead><tr><th>i get displayed first</th></tr></thead> <tfoot><t ...

Creating an If statement tailored for a particular image source: a step-by-step guide

In the program I am running in Dreamweaver, there is a specific line of code that looks like this: function go() { if((document.test.test1.src == document.test.test2.src && document.test.test2.src == document.test.test3.src )) ...... ...... ..... ...

Node.js exporting fails due to an undefined variable

When attempting to export variables in Node.js, I keep receiving an undefined error. I'm not sure what the issue is, can anyone provide assistance or suggestions? Here is a snippet from index.js: var test = 10; module.exports.test = test; And here i ...

What causes the offsetWidth attribute to be zero in an array of elements within the DOM?

I am encountering an issue with a script that sets widths for certain elements in the Dom. Specifically, when I use the code var elements = document.querySelectorAll("p.caption"), the first 12 elements display the correct offsetWidth, but the remaining hal ...

Ways to integrate a security protocol with a graphql resolver

I'm currently diving into the world of graphql and I'm facing a challenge with incorporating an authentication/authorization system into my project. I stumbled upon an example on Medium, but I'm struggling to grasp how a guard connects with ...

Generating a list of objects from an array of strings

I am currently facing an issue in my code and I could use some help with it. Below are the details: I have a array of string values containing MAC addresses and constant min & max values. My goal is to map over these MAC values and create an array of obje ...

What steps should I take to make my Vue JS delete function operational?

As I work on developing my website, I've encountered some challenges. Being new to coding, I'm struggling with creating a functional delete user button. When I click delete, it redirects me to the delete URL but doesn't remove the entry from ...

JQuery form not triggering the submit event

Currently, I am facing some issues with my code while trying to trigger on submit event on a form and validate it. The main problems I encountered are that the onsubmit event is not being triggered, and the input field of type email is not validated proper ...

Can you clarify the dissimilarity between `knex().select("id").from("users")` and `knex("users").select("id")` in Knex?

I have successfully connected knex with mysql and am working on a login form linked to a mysql database. Currently, I am performing a login check and I'm curious if there is any distinction between the following two queries: knex().select("id").from( ...

React.js is throwing a 429 error message indicating "Too Many Requests" when attempting to send 2 requests with axios

Currently, I am in the process of learning React with a project focused on creating a motorcycle specifications search web application. In my code file /api/index.js, I have implemented two axios requests and encountered an error stating '429 (Too Ma ...

When attempting to use the $http get command, an error may occur due

Is there a way to capture these errors in an Ionic application? ionic.bundle.js:25000 GET net::ERR_CONNECTION_REFUSED Using the following code snippet: $http.get('http://' + ip + '/?custom=1&cmd=' + cmd); I have attempted var ...

When using Thunderbird Webextensions, calling .messages.getFull() may result in the Exception 0x80004005 being raised, specifically indicating

This question is a follow-up to a previous question/answer found at: In this scenario, the code attempts to retrieve a list of accounts, select the emailAccountName, get a MessageList object from the specified wantedMailFolderType, and then access a Messa ...

The beauty of asynchronous GET requests in VueJS

As a newcomer to VueJS, I am exploring how to make a GET request to the GitHub API. Initially, I made a request to sort users by follower count, resulting in an array ordered in descending order of user logins. Following that, I sent another GET request to ...

Submitting a form within AJAX-powered tabs (using the Twitter Bootstrap framework)

I have encountered an issue while trying to submit a form that is located within tabs. The content of these tabs is generated through AJAX. My problem arises when I submit the form - the page refreshes and loads the "default" tab, causing the PHP function ...

Creating unique appbars for different sections on my sidebar in ReactJs

I am trying to implement a responsive drawer and AppBar using material-ui (@material-ui/core). My goal is to display a specific AppBar for each section of the drawer. For instance, when the user navigates to the Timetable section, I want the AppBar label t ...

Utilize Next.js and GSAP to dynamically showcase images upon hovering over the title

I have a dynamic list of titles that I want to enhance by displaying images when hovering over each title. The issue I'm facing is that when I hover over one title, all the images display at once. As a React beginner, I believe the solution should be ...

Updating columns in MongoDB using arrays in JavaScript has just gotten easier

When trying to update a mongoDB collection with an array value, the update fails without any error message. This method causes the issue: var arr = ["test","test1","test2"]; $.ajax('http://my.mongodb.com/collection?id=80a2c727de877ac9' , { ...