Encountering an issue with subscribing wait times

Whenever a button is clicked within my application, I have a requirement to upload specific items to the API before proceeding with the next functionality.

I've experimented with various approaches to ensure that the code waits for execution, but it seems to be advancing without completing the necessary tasks.

Below is an excerpt of the code snippet:

// Triggered on button click
onSendEmailClick(): void {
    if (this.selectedEmail.Content) {
        let attachments = this.assignEmailContent();
        this.fireAfterCompleted(attachments);
    }
}

// Executed upon button click
assignEmailContent() {
    return this.assignEmailAttachments();
}

// It's crucial for attachmentArray to be fully populated before being returned
async assignEmailAttachments() {
    let attachmentArray: any[] = this.selectedAttachments.map(async (item) => {
        const response = await this.subscribeToContainerItem(item);
        attachmentArray.push(response);
    });
    return attachmentArray;
}

// Invokes an API method to fetch item
async subscribeToContainerItem(item: any) {
  this._azureStorageService.getContainerItemByContainerIdItemName(this._routeIdService.getStorageContainerId(), item.Name).subscribe(async (res: any) => {
        return ({ filename: item.Name, path: res.url });
    }, err => {
        return (err);
    });
}

// Handles API Request
getContainerItemByContainerIdItemName(containerId: string, itemName: string) {
    let httpOptions = this.prepareOptions();
    return this._http.get(environment.API + containerId + '/' + itemName, httpOptions);
}

The method assignEmailAttachments needs to await the response before moving forward. Any guidance on this issue would be greatly appreciated.

Answer №1

It seems that subscribeToContainer may need some adjustments to convert an asynchronous callback based API (such as RxJs Observable) to a Promise. You can achieve this by using the Promise constructor:

subscribeToContainerItem(item: any) {
    // Create a new Promise instance immediately
    return new Promise((resolve, reject) => {
        // Call the inner API and wait for the async response
        this._azureStorageService.getContainerItemByContainerIdItemName(this._routeIdService.getStorageContainerId(), item.Name)
            .subscribe(
                // Resolve the promise in the callback function
                res => resolve({ filename: item.Name, path: res.url }), 
                // Reject the promise in case of error
                err => reject(err)
            );
    });
}

When dealing with attachments, you will need to ensure all attachments are populated before proceeding. Here is a slightly shorter version of the function:

assignEmailAttachments() {
    // Map each element to an async operation that resolves with a populated item
    const populatedAttachmentPromises = this.selectedAttachments.map(item => this.subscribeToContainerItem(item));
    // Wrap them in a promise that resolves when all items are populated
    return Promise.all(populatedAttachmentPromises);
}

Then in the onClick handler, make sure to wait for the promise to resolve before continuing:

onSendEmailClick(): void {
    if (this.selectedEmail.Content) {
        this.assignEmailContent()
            .then(attachments => this.fireAfterCompleted(attachments));
    }
}

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

What is causing the .responseToString function to be recognized as not a function?

Consider the following scenario with Typescript: interface IResponse { responseToString(): string; } export default IResponse; We have two classes that implement this interface, namely RestResponse and HTMLResponse: import IResponse from "./IRespo ...

What is the best method for inserting a hyperlink into the JSON string obtained from a subreddit?

const allowedPosts = body.data.children.filter((post: { data: { over_18: any; }; }) => !post.data.over_18); if (!allowedPosts.length) return message.channel.send('It seems we are out of fresh memes!, Try again later.'); const randomInd ...

Is it possible to customize the color of the placeholder and clear-icon in the ion-search bar without affecting

I am working with two ion-search bars and I need to customize the placeholder and clear icon color for just one of them. <ion-searchbar class="search-bar" placeholder="search"></ion-searchbar> My goal is to target a specific i ...

Unable to determine the data type of the JSON object during the

I'm having trouble reading an Object type of json... Here is the json I'm working with: body: { "111": { "name": "name1", "status": 10000 }, "222": { "name": "name2", "status": 20000 }, "333": ...

Exploring the capabilities of indexing an array within an array in Nativescript

I am working with JSON data retrieved from an API and trying to figure out how to index an array inside an array using Nativescript. JS: cart [{ JS: "_id": "5d3988cd287bad2943686920", JS: "userid": "11E76234942299FCC13FFA163EDC2079", JS: "products": ...

Create a checklist with unique identification, value, and description by utilizing an array of objects

Utilizing React with Typescript, I am tasked with constructing the React component MultiSelectCheckBoxes by supplying an array of Objects of type Color to the constructor: The structure for a checkbox list should be like this: const options = [{ "id": ...

The code compilation of Typescript in a Dockerfile is not functioning as expected due to the error "Name 'process' cannot be found."

Here's the Dockerfile I'm working with: FROM node:latest WORKDIR /usr/src/app ENV NODE_ENV=production COPY package*.json . RUN npm install && npm i -g typescript COPY . . RUN tsc CMD [ "node", "./dist/index.js&qu ...

Karma Unit test: Issue with accessing the 'length' property of an undefined value has been encountered

While running karma unit tests, I encountered a similar issue and here is what I found: One of my unit tests was writing data to a json file, resulting in the following error: ERROR in TypeError: Cannot read property 'length' of undefined a ...

Together, we have a shared Yarn JS directory for both the client and server components,

The scenario: both the client and server share a folder named shared when we make changes to the shared folder in our development process, we need the corresponding references to update in both the client and server the server seems to w ...

ERROR TS1086: A declaration of an accessor within an ambient context is not allowed. Accessor for firebaseUiConfig(): NativeFirebaseUIAuthConfig

Trying to create a Single Page Application with Angular/CLI 8. Everything was running smoothly locally until I tried to add Firebase authentication to the app. Upon compiling through Visual Studio Code, I encountered the following error message: ERROR in ...

Setting the initial navigation theme based on route parameters from an external source, not within the StackNavigator

Is there a way to set the initial navigation theme based on the current route params without rendering the NavigationContainer and causing a flash of content with the default theme? Can the route be accessed from outside of the NavigationContainer without ...

The TS2583 error in TypeScript occurs when it cannot locate the name 'Set' within the code

Just started my Typescript journey today and encountered 11 errors when running tsc app.ts. Decided to tackle them one by one, starting with the first. I tried updating tsconfig.json but it seems like the issue lies within node_modules directory. Any help ...

The extended class possesses a distinct type from the base class, which is reinforced by an interface

Is it possible to write a method that is an extension of a base class, but with a different return type, if supported by the shared interface, without adding a type declaration in class 'a'? In practical terms, classes a & b exist in JavaScript ...

Guide to slicing strings specifically with numerical characters at the end

I've encountered a challenge. I need to slice the last two characters in a string, but only for strings that contain numbers. I attempted using "nome": element.nome.slice(0,-2) and now I require some sort of validation. However, figuring out how to do ...

What could be causing my Angular project to not run properly without any changes made after creating a new component that I want to include in app.component.html?

Greetings, I am just starting out with Angular 17 and I am currently going through the Tour of Heroes course on the official website. Following the tutorial's instructions, I created a new component called 'heroes' after setting up my projec ...

Utilizing an external type definition in JSDoc @typedef

I'm encountering an issue with reducing redundancy when defining my imported types. I am trying to streamline the process, but unfortunately I am running into errors. /** @typedef {import("../types/util")} util @typedef {util.mapBehaviors} m ...

Display "No Results Found" in Angular and Ionic 4 when the observable is empty

Below is the HTML code: <ion-list> <ion-radio-group> <ion-item class="ion-no-padding" *ngFor="let service of services | async"> <ion-label> <ion-grid> <ion-row> < ...

I cannot access the 'isLoading' state in React Query because it is undefined

Since updating to the latest version of react query, I've been encountering an issue where the 'isLoading' state is returning undefined when using useMutation. Here's the code snippet in question: const useAddUserNote = (owner: string) ...

Confidently set up a proxy that is recursively nested and strongly typed

I have a collection of objects where I store various content for a user interface. Here is an example: const copy = { header: { content: 'Page Header' }, main: { header: { content: 'Content Subheader' }, body ...

What is the optimal location for storing a chosen collection of items?

There are multiple lists of elements available: let list1 = [1,2,3,4]; let list2 = [1,2,3,4]; let list3 = [1,2,3,4]; Each list is being iterated through in a loop: <div *ngFor="let el of list1" (click)="set(el)">{{el}</div> <div *ngFor= ...