Trouble with FetchClient and Promises

I am trying to get a list back from a script via the fetchClient to put inside a dropdown in my html view client.

I have defined the fetchClient in client.js like this:

import jquery from 'jquery';
import {HttpClient} from 'aurelia-fetch-client';
import {inject} from 'aurelia-framework';

window.jQuery = jquery;
window.$ = jquery;

@inject(HttpClient)

export class Client {

  httpClient;

    constructor(httpClient)
    {
        this.client_list = null;
        //this.valid_client_list();
        this.cookie = null;
        this.getClientList();
        //this.valid_client_list();
        let fetchClient = httpClient;
    }

    async getClientList() {

      let clientList = this.client_list;

      if(clientList !== null) { return clientList; }
  
      const self = this;

      self.cookie = document.cookie.split("=");
      self.user = self.cookie[1];

      if ( self.user )
      {
          var url = 'http://[ip address]/client_list.pl';
    

      //assuming you have configured the fetch client as shown in docs      
      //clientList = this.client_list = await this.fetchClient
      return await this.fetchClient
            .fetch(url, {
                method: 'GET',
                 // other necessary  options
                 url: url, // URL of the Perl script
                 contentType: "application/json; charset=utf-8",
                 dataType: "jsonp",
                 headers: { 'Access-Control-Allow-Origin': '*' },
                 mode: 'no-cors',
                 crossDomain: true,
                 jsonp: 'callback',
                 // send username to build client list
                 data: "REMOTE_USER=" + self.user,
                 // script call was *not* successful
                 error: function(XMLHttpRequest, textStatus, errorThrown) { 
                   console.log("responseText: " + XMLHttpRequest.responseText 
                     + ", textStatus: " + textStatus 
                     + ", errorThrown: " + errorThrown);
                 }, // error 
                 // script call was successful 
                 // data contains the JSON values returned by the Perl script
                 success: function(data){
                   if (data.error) { // script returned error
                     console.log( 'error: ' + data.error );
                   } // if
                   else { // got the list
                     //for (var i = 0; i < data.clients.length; i++ )
                     //{
                     //    console.log( 'client: ' + i + ' ' + data.clients[i] );
                     //}
                     
                     resolve(data);
 
                     //self.client_list = data.clients;           
                   } //else
                 } // success
               } ) // fetch
             .then((response) => response.json());
  
       //return clientList;
              }
    } 
}

and customer.js where I use Client to call the fetch and give me back the array:

import './style.css';
import jquery from 'jquery';
import {Client} from './client';
import {inject} from 'aurelia-framework';


window.jQuery = jquery;
window.$ = jquery;

@inject(Client)

export class Customer {
    constructor(client, api) {

        this.client = client;
        this.api = api;
}
    async clientList () {

            
        //let clients = await this.client.getClientList();
        this.clients = await this.api.getClientList();
        console.log( 'async client: ' + this.clients );
    }
}

No matter what I try, I get the following error:

Uncaught (in promise) TypeError: Cannot read property 'fetch' of undefined at Client._callee$ (client.js?7ed9:24)

When I click on the client.js, it pulls up this line as the complaint:

async getClientList() {

I don’t know what I’m doing wrong.

1 Like

You injected client, so it should be this.client.getClientList(), that this.api is undefined because of no injection.

1 Like

I changed the line to this.client.getClientList(), and I am still getting the undefined error.

1 Like

I figured out the problem:

I had been calling this.getClientList() in the constructor, and it kept returning undefined from that point.

Now that I commented that out, it’s returning a promise Object.

I can’t figure out how to access the data from the promise Object.

I have the following in client.js

.then((response) => {
                let clientList = response.json(); 
                console.log( 'response: ' + clientList ); 
//logging this gets [object Promise]
              
                return clientList;
              });

and then this in customer.js:

  async bind () {
        this.clients = await this.client.getClientList();
        console.log( 'async client: ' + this.clients );
//logging this gets [object Object]
    }

But I can’t access the list I’ve returned.

1 Like

That API returns a promise too, change to

let clientList = await response.json();

FYI, when you log a JS object, don’t turn it into unreadable string, supply it as another argument, browser will log the structured (if it is) object in console.

console.log( 'response: ', clientList );
1 Like

I tried using let clientList = await response.json(); and I got the error: Can not use keyword 'await' outside an async function.

This is my async function in client.js:

    async getClientList() {  
      const self = this;

      self.cookie = document.cookie.split("=");
      self.user = self.cookie[1];

    if ( self.user )
    {
      var url = 'http://[ip address]/client_list.pl';
      url += '?REMOTE_USER=' + self.user;

      //assuming you have configured the fetch client as shown in docs      

      return this.httpClient
            .fetch(url )
              .then((response) => {
                let clientList = await response.json(); 
                console.log( 'response: ', clientList ); 
              
                return clientList;
              });
      }
    } 

If I remove the await, and do the logging like you suggested, I can see the data I want to access in the PromiseValue as clients with all the data there.

How do I return this?

Even logging in customer.js as this:

console.log( 'async client: ', this.clients );

I can see the data, but if I try to iterate over it, the code doesn’t run?

What am I missing?

Thanks in advance for all your help.

1 Like

Mark the func as async.

.then(async (response) => {
                let clientList = await response.json(); 
1 Like

Thank you.

Also I figured out how to access the data.

I needed:

this.clients.clients because the json object returns as an array of clients.

2 Likes