0

I'd like to use ember-concurrency to handle batch validation of a collection of addresses. The address validation is done by a third party API that calls a server-side function that then 'calls back' to the client when the server has completed its work.

It seems like this would be a place to use the ember-concurrency add-on, but i can't figure out how to use it correctly. I think the challenge is that the api call to server returns immediately after the server side process is kicked off. How do i make ember-concurrency aware of the connection between the call to the server and the callback function so that the 'task' waits for the callback to be completed as a sign that the task has been completed? The way i have the code working now, 'results' is (understandably) always null.

import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { task } from 'ember-concurrency';

export default class BatchAddressInputComponent extends Component {
    @service api;
    addressList = "";

    //addressList populated from a TextArea
    @task *DoAddressValidation ()
    {
        let results = yield this.api.BatchQueryAddresses(this.addressList);
        alert(results); //not surprisingly, 'results' is always null
    }
}
    
    
import Service from '@ember/service';

export default class ApiService extends Service {
  _api;

  //API *should* be available as a global object, imported as a <script> on
  // application start-up.
  constructor() {
    super(...arguments);
    this._api = API;
  }

  BatchQueryAddresses(addressList) {
    this._api.BatchQueryAddress(addressList, 2, this._queryAddressCallback, null, 2000);
  }

  _queryAddressCallback(result, error) {
    if (error) {
        alert("Error: " + result);
        return;
    }
    var j = JSON.stringify(result, null, ' ');
    return(j);
  }
}
tripper
  • 27
  • 1
  • 7

1 Answers1

1

You need to return a Promise. The new Promise(...) constructor is made for exactly this:

BatchQueryAddresses(addressList) {
  return new Promise((resolve, reject) => {
    this._api.BatchQueryAddress(
      addressList,
      2,
      (result, error) => {
        if (error) {
          reject("Error: " + result);
        } else {
          const j = JSON.stringify(result, null, ' ');
          resolve(j);
        }
      },
      null,
      2000
    );
  });
}
Lux
  • 17,835
  • 5
  • 43
  • 73
  • lux - thanks for the code. when running it, the Promise is returned with this error "Cannot read properties of undefined (reading 'BatchQueryAddress')". I'm unsure if that is coming from the third party api or not. when i call the Api method BatchQueryAddress as an @action and using the callback, the function returns the expected results. – tripper Oct 10 '21 at 05:11
  • @tripper the message indicates `this._api` is undefined. Did you maybe not use an arrow function? – Lux Oct 15 '21 at 02:36
  • 1
    it pains me to admit it, but i had a capitalization mistake in my code: this._api should have been this._Api. Your code works as expected after fixing my mistake. – tripper Oct 18 '21 at 16:30