Function returning promise asynchronously, but caller function failing to resolve the promise

I have been researching similar items without success and I realize that I need a better understanding of promises, but I am facing some challenges.

My project involves Ionic 4/Angular 8 with an Azure-based backend. I am trying to display images from Azure storage by appending a key to the URL.

In order to avoid repetitive code for checking the key, getting a new one if it's expired, and appending it to the URL on every page, I decided to create a service function for this purpose. However, the calling function does not seem to wait for the '.then' method, resulting in 'undefined' values (I think). Ideally, I just want the service to return a string.

Here is the service function I have:


async getStorageURLWithKey(url: string): Promise<string> {
  const nowplus5 =  addMinutes(Date.now(), 5);
  console.log(nowplus5);
  console.log(url);
  console.log(this.azurekey);
  if (!this.azurekey || isBefore( this.azurekey.Expires, nowplus5 )) {
    console.log('Getting new Key');
    const keyObj = await this.getAzureKeyServer().toPromise();
    await this.saveAzureKeyStore(keyObj);
    return url + keyObj.Key;
  } else {
    console.log('Key is valid' + this.azurekey.Expires);
    const rval = new Promise<string>(function(res) {
      res(url + this.azurekey.Key);
    });
    return rval;
  }
}

My calling function looks like this:


getBizImg(): string {
  console.log('GetBizImg');
  if (this.business.Id) {
    this.userService.getStorageURLWithKey(this.business.ImageURL).then((url) => {
      console.log(url);
      return url;
    }, reject => {
      console.log('Rejected:' + reject);
    });
  } else {
    return '';
  }
}

When I call the getBizImg function from ngOnInit, it returns 'undefined' before the 'console.log(url)' line.

Here's the ngOnInit code:


ngOnInit() {
  const imageurl = this.getBizImg();
  console.log(imageurl);
}

The call should ideally come from the HTML page:


<ion-content padding>
   <ion-img [src]="getBizImg()" ></ion-img>
</ion-content>

Once I resolve this issue, I can uncomment the code in the HTML page to prevent an endless loop.

It seems like I need to make the getBizImg() function async and await the call to return a promise:


ngOnInit() {
  this.getBizImg().then((wibble) => {
    console.log(wibble);
  });
}

Here is the updated getBizImg function:


async getBizImg(): Promise<string> {
  console.log('GetBizImg ID= ' + this.business.Id);
  if (this.business.Id) {
    const url = await this.userService.getStorageURLWithKey(this.business.ImageURL);
    console.log(url);
    return url;
  } else {
    return '';
  }
}

However, this approach does not give me the simple string needed for the HTML.

After trying some different approaches, including using the Angular async pipe, the issue persists with an endless loop. It seems like there might be a more fundamental error that I am missing.

Would appreciate any advice or suggestions to resolve this issue.

Answer №1

The function getBizImg() does not directly provide a URL; instead, it is returned within the callback function of getStorageURLWithKey() promise.

To display the URL using the async pipe, modify the method type to Promise<string> and return the promise:

getBizImg(): string {
  console.log('GetBizImg');
  if (this.business.Id) {  // Business object is available
    // Return the promise here
    return this.userService.getStorageURLWithKey(this.business.ImageURL).then((url) => {
      console.log(url);
      return url;
    }, reject => {
      console.log('Rejected:' + reject);
    });
  } else {
    return '';
  }
}
<ion-content padding>
   <ion-img [src]="getBizImg() | async"></ion-img>
</ion-content>

Answer №2

It seems like your async function getBizImg() is correct. You can implement it in the following way:

ngOnInit() {
  this.getBizImg().then((result) => {
    console.log(result);
    // Assign the result to this.urlImage
  });
}

Make sure to add a urlImage property on your component. Then, in the HTML:

<ion-content padding>
   <ion-img *ngIf="urlImage" [src]="urlImage" ></ion-img>
</ion-content>

If you prefer calling it directly from the HTML, you can try using the asyncPipe. Check out the documentation here:

<ion-content padding>
   <ion-img [src]="getBizImg() | async" ></ion-img>
</ion-content>

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

Invoking a nested function within an array

I need to trigger a function with a button click. The function I want to call is nested within another function, which is part of an array. demo = { volej: function(param) { (new initChartist).users(param); }, initPickColor: function(){ ...

Unable to display shadows in Three.js

I've hit a roadblock with the shadow effect at the moment, despite trying various solutions for hours, it's still not appearing. Can anyone point out what I may have done incorrectly? Below is the code snippet for my current scene: //Setting up ...

Using Handlebars JS to incorporate HTML tags such as <li>, <br>, and more in your data

Is there a way to use handlebars to display a list of data in an unordered format, with "title" and "articles" as the main categories? The issue arises when some of the articles contain HTML tags, such as <a> for links. In my current code, instead of ...

Struggling with overlaying Bootstrap modals on top of each other

This idea is inspired by the topic Multiple modals overlay I am working on developing a folder modal that allows users to either 1) open an existing file or 2) create a new file within each folder modal. To see how it functions, please run the code below ...

Utilizing the .add() method in Firebase Cloud Firestore for working with nested

In the documentation for Firebase, it mentions updating nested objects. You can find out more about this here: https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects Here is my data structure: let ref = db.collect ...

Is there a way to switch colors with the click of a button?

I'm looking to incorporate a bootstrap color picker into my website. I want the button inside this div to trigger the color chart and change the background color of the entire div when clicked. Can anyone help me achieve this functionality? <d ...

Incorporating mootools scripts into a gwt application

My issue involves creating an animation on a Composite that should start when data is loading. To test this, I created animations on regular divs using HTML: <div class="LoadDataWidget"> <div id="arrow" class="greenArrow"></div> < ...

Client-side resizing an image before sending it to PHP for uploading

Greetings! Currently, I am utilizing a JavaScript library from this source to resize images on the client-side. The image resizing process works successfully with the following code: document.getElementById('foto_select').onchange = function( ...

Is there a way to apply the active class without relying on an anchor element?

After creating a one-page website, I utilized JavaScript to prevent the hash from appearing in the URL. Here is the HTML code: <ul class="click crsl"> <li><a class="page1 dot active"></a></li> <li><a class=" ...

Determining the angular difference between the direction of particle motion and a straight line

Currently, I am in the process of developing a simulation involving a bouncing ball. In this simulation, users have the ability to place lines on the canvas that the ball can collide with by dragging from one point to another. There are specifically four t ...

Trigger is not activated by dynamically created element

I am dealing with a block of code that is dynamic and looks like this. var li3 = document.createElement('li'); li3.classList.add("col-sm-3"); li3.classList.add("no_padding"); var inner = ""; inner = inner ...

Incorporate object keys into an array using JavaScript

Query: I'm working on a JavaScript project and I have an array that looks like this: [6.7, 8, 7, 8.6]. I need to transform this array into an array of objects with named properties: [{y: 6.7} , {y: 8}, {y: 7}, {y: 8.6}]. Can someone guide me on how to ...

Can MUI FormControl and TextField automatically validate errors and block submission?

Are MUI components FormControl and TextField responsible for error handling, such as preventing a form from being submitted if a required TextField is empty? It appears that I may need to handle this functionality myself, but I would like some clarificatio ...

Lining Up Radio Buttons Horizontally Using CSS: Alignment Issues in Mozilla and Chrome

I have recently started learning CSS and am facing an issue with the alignment of radio buttons. They do not align properly in Chrome and Firefox, although they display correctly in Explorer. Any assistance on this matter would be greatly appreciated. Th ...

What could be the reason for the absence of the observable item value appearing in the HTML template?

Working with Angular4, I recently created a straightforward list-details example. However, when attempting to display item details on the details page, specifically for items of Observable type class, I encountered some obstacles. Below is the snippet of c ...

Struggling with combining model and textures in three.js

Here in this fiddle, you can find an example of the issue I am facing: http://jsfiddle.net/saward/78Bjk/7/ If you uncomment scene.add(tree_mesh) and scene.add(mesh2), and comment out scene.add(mesh), you will be able to see both objects. However, when I m ...

The JavaScript animations in AngularJS using ng-class are not being activated

I've been attempting to apply js-defined animations to the ng-class directive using the standard syntax of add and remove, but for some reason, the animations are not running. After checking the logs, it seems that the add and remove functions are not ...

Unable to connect to Alpine store from an external source due to a typescript error

Here is how I have configured my Alpine store: Alpine.store( 'state', ({ qr: '' })) Now, I am attempting to update it from an external source as follows: Alpine.store( 'state' ).qr = 'test' However, I am encounte ...

Having trouble editing a form with React Hooks and Redux?

Seeking assistance with creating an edit form in React that utilizes data stored in Redux. The current form I have created is displaying the values correctly, but it appears to be read-only as no changes are being reflected when input is altered. Any advic ...

Need at least one of two methods, or both, in an abstract class

Consider the following scenario: export abstract class AbstractButton { // Must always provide this method abstract someRequiredMethod(): void; // The successor must implement one of these (or both) abstract setInnerText?(): void; abst ...