Promises with angularJS and Typescript

I have the following function, my goal is to push to the items list, when the components can identify their parent item. The problem that I have is that when I am pushing to the list console.log() shows me that the object is in there, but when I return the list and catch it in another function, there is nothing in the list. I think that the items list is returned before the code above it is done.

 private get_items_for_request() {
   return this.Item.forRequest(this.request.id, ['group'])
     .then((_items) => {
       var items = [];
       for (var item of _items) {
         return this.ItemComponent.forItem(item.id, ['type'])
           .then((_components) => {
             for (var component of _components) {
               if (component.type.can_identify_item) {
                 items.push({
                   group_id: item.group.reference,
                   identifier_code: this.remove_check_digit_if_necessary(
                       component.identifier_code),
                   quantity: 1
                 });
                 break;
               }
             }
           }, (reason) => {
             this.Toast.error(
                this.gettextCatalog.getString('components.load_failed'));
             return [];
           });
       }
       return items;
     }, (reason) => {
       this.Toast.error(
           this.gettextCatalog.getString('items.failed_load'));
       return [];
     });
 }

Answer

I’m afraid the trouble is with your approach, not with the code itself. A promise is just that – a promise of data some time in future. So, when you function returns (immediately), the promise is not resolved yet and the data your caller function captures is still empty. I don’t see console.log() in your code, but would suspect you put it somewhere inside then(), which will be called once data has been received. So you will see data being logged. Trouble is by that time get_items_for_request() has already returned and your caller function has already moved on.

If you want to use a promise, you have to use a callback to be called once promise is resolved. But if you want actual data returned to the caller you need to fetch data synchronously.

For the synchronous fetch, check this response. But beware that synchronous fetch will hurt responsiveness of your script.

For an asynchronous fetch (using promises), you need to define a callback called once all data has been fetched. I won’t try to fix your code, but it should go along the following sketch in javascript. Though keep in mind it’s just a sketch.

function get_items_for_request(onSuccess) {
  var items = []
  var total = -1
  var sofar = 0;
  this.Item.forRequest(this.request.id, ['group'])
     .then(function (_items) {
       var items = [];
       total = _items.length // remember how many nested calls will be made
       for (var item of _items) {
         this.ItemComponent.forItem(item.id, ['type'])
           .then(function (_components) {
             // push received data to the items array here
             sofar++
             if (sofar == total) { // all done 
               onSuccess(items)
             }
          }
       }
   }
} 

Leave a Reply

Your email address will not be published. Required fields are marked *