Waiting for the completion of the previous observable in an RxJS Interval Observable

I'm trying to create an interval observable that waits for the last execution before proceeding. Here are some attempts I've made:

First attempt:

interval(1000)
  .subscribe(async x => {
    await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10000) + 1000));
    console.log('Got counter', x);
  });

This resulted in: 4, 1, 2, 6, 9, 7, 6, 3...

Second attempt, but not ideal:

let alreadyRunning = false;
interval(1000)
  .pipe(skipWhile(() => alreadyRunning))
  .subscribe(async x => {
    alreadyRunning = true;
    await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10000) + 1000));
    console.log('Got counter', x, alreadyRunning);
    alreadyRunning = false;
  });

The skipWhile operator only waits before the first condition is met.

Next, I tried using switchMap which also did not work:

interval(1000)
  .pipe(switchMap(() => from(new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10000) + 1000))))
  .subscribe(async x => {
    console.log('Got counter', x);
  });

Another unsuccessful attempt:

interval(1000)
  .pipe(switchMap(x => from(async () => {
    await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10000) + 1000));
    console.log('Got counter', x);
    return x;
  })))
  .subscribe(async x => {
    console.log('X', x);
  });

Is there a solution to achieve this? Waiting for the last observable to finish?

//edit 1: What am I looking for?

I have an interval that makes an HTTP Request. If one request takes too long and the next interval starts, it results in multiple requests being executed simultaneously. I want to avoid this scenario.

MergeMap also did not provide the desired outcome:

interval(1000)
  .pipe(mergeMap(x => from(new Promise(resolve => setTimeout(() => resolve(x), Math.floor(Math.random() * 10000) + 1000))))
  .subscribe(async x => {
    console.log('Got counter', x);
  });

Answer №1

It's unclear what you're inquiring about, but if user AJT82 is correct (meaning you want to eliminate any emissions from the interval while the previous request is still ongoing)

Here is my suggested approach for implementing this scenario:

interval(1000).pipe(
  tap(_ => console.log('interval hits every second!')),
  exhaustMap(_ => {
    console.log("request has started!")
    return timer(3000).pipe( // simulating a process that takes 3 seconds to complete
      tap(_ => console.log("request has finished!"))
    )
  })
).subscribe({
  next: v => console.log("Value emitted: ", v),
  error: e => console.log("Error emitted: ", e),
  complete: () => console.log("Complete emitted")
});

A Note on async/await

Observables encompass promises and provide additional functionality. This means that actions performed with promises can also be achieved using observables.

Unlike Promises, Observables do not have built-in syntactic sugar like async/await.

Observables and Promises can work together seamlessly. Many operators are designed to handle both promises and observables by automatically converting promises under the hood.

This flexibility proves useful when your project utilizes one type and you wish to incorporate a library reliant on the other.

On the flip side, if your code primarily relies on observables, there is typically no valid reason to resort to promises. Doing so may indicate an issue in your code structure and should be avoided unless absolutely necessary.

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

Experiencing issues with ngx-masonry functionality in Angular application, resulting in images appearing clustered and overlapping

Working on a layout design in Angular 9 and utilizing the ngx-masonry package (https://www.npmjs.com/package/ngx-masonry) to achieve a specific grid structure. Here’s a snippet of my code: <div class="container pt-5"> <ngx-masonry ...

Utilize fetch API in React to streamline API responses by filtering out specific fields

I have received an API response with various fields, but I only need to extract the description and placeLocation. results: [{placeId: "BHLLC", placeLocation: "BUFR", locationType: "BUFR",…},…] 0: {placeId: "BHLL ...

Adding images to your SVG using Bobril is a simple process that can add visual

I have been attempting to insert an image into an SVG using Bobril, but the following code is not functioning as expected: { tag: 'svg', children: { tag: 'image', attrs: { 'xlink:href': &ap ...

What is the best method for transferring form data to a string and storing it in localStorage effectively?

Is this the most efficient method for extracting form data into a string and storing it in localStorage? I developed this method independently, but I'm not an experienced programmer. It seems to work for my needs, but I'm unsure if it's com ...

Sharing data between React JS components Passing information between different components in React JS

My NavBar.js component contains login information for the logged-in user. It displays "Welcome" along with the user details when the user is logged in. Now, I want to replicate this functionality in the ProductList.js component so that when a user posts a ...

What is the method for accessing the AG-Grid Grid API beyond the Vue component?

In my application, I have a component called Home and another one called AgGrid. The AgGrid component is displayed within the Home component, containing the actual AG-Grid. Here's how the Home component is structured: <template> <AgGrid :ro ...

Creating a layout of <video> components in vue.js, complete with the ability to rearrange and resize them through drag and drop functionality

Despite trying numerous libraries and Vue.js plugins, I have yet to find one that meets all of my requirements. I am in need of creating a grid of video HTML elements that are draggable and resizable with a consistent aspect ratio of 16:9. Additionally, I ...

Convert a relative path to an absolute path using the file:// protocol

When I scrape a website with similar html content, I come across the following code: <a href="/pages/1></a> In addition to this, I have access to the window.location object which contains: origin:"http://www.example.org" This allows me to ...

Arrange the Elements of Select Options

I am currently facing an issue with organizing the elements in my select list. I have two interconnected lists, one containing a list of "models" which I have successfully sorted using the following function: var sel = $('#model'); var opts_lis ...

Using jQuery Ajax and PHP to retrieve data from a database based on multiple checkboxes

my code currently only selects one checkbox at a time. What I am trying to achieve is when clicking on the first checkbox, it should display a result. Then, if the second or third checkbox is clicked, all checkboxes should be submitted together to the proc ...

Having trouble with NPM install because of a node-gyp issue?

We're facing issues with running "npm install" on our project. The error message states that a specific file cannot be located: fatal error C1083: Cannot open include file: 'windows.h' This error seems to be originating from the node-gyp mo ...

"Utilizing Javascript in an ERB view file within the Rails framework

In my .js.erb file, I need to execute a conditional statement when an ajax call is triggered. Below is the code snippet: function updateContent() { $('.organiser__holder').html('<%= escape_javascript render("filter_links") %>' ...

ReactJS encountering an invalid dropzone element

Encountering the error "invalid dropzone element". I added var Dropzone = require('react-dropzone'); to my webpack.config.js file in hopes of activating the Dropzone element. This is what is included in my JavaScript file, copied from a Gith ...

Unable to locate 'react' for mdl module

Currently working on my first website using react, following a tutorial available at this link I am attempting to install and utilize the material lite module, but encounter a compilation error when starting npm with the following message: Error: Module ...

Developing a bespoke React component library - encountering an issue with 'react module not found' during Jest testing, as well as using testing-library

I am in the process of creating a bespoke react component library to be shared across various applications. To build this library, I am utilizing rollup and referencing resources such as this blog post along with others: https://dev.to/alexeagleson/how-to- ...

Custom "set attribute" feature in TypeScript

One issue I faced was resolved by creating the function shown below : function setProperty<T extends Record<string, string>>(obj: T, key: keyof T) { obj[key] = "hello"; } However, when I tried to compile the code, I encountered an ...

Customizing line charts with D3.js and AngularJS for ultimate visual impact

Working on a project involving the creation of a line chart using D3.js library and AngularJS within an Ionic framework. I am looking to customize the color of data points based on the Y-axis values. For example, if the value falls between 0-30, I want t ...

Getting a specific piece of information from a JSON file

I am encountering an issue with my JSON file collection. When I access it through http://localhost:5000/product/, I can see the contents without any problem. However, when I try to retrieve a specific product using a link like http://localhost:5000/product ...

"Exploring the process of extracting data from a JSON URL using NextJS, TypeScript, and presenting the

After tirelessly searching for a solution, I found myself unable to reach a concrete conclusion. I was able to import { useRouter } from next/router and successfully parse a local JSON file, but my goal is to parse a JSON object from a URL. One example of ...

Automatically navigate to a different page using JavaScript after 5 seconds without interrupting the execution of other code

Is there a way to redirect to a specific URL after 5 seconds without halting the execution of other code on the page? I want all the other code to run first before triggering the redirection. Wrapping the entire page in a setTimeout block is not an option. ...