Как ждать Http-запросов в цикле, чтобы завершить выполнение, чтобы продолжить работу с некоторым зависимым фрагментом кода? - PullRequest
0 голосов
/ 04 июля 2019

Мне нужно сделать вызов API (основной вызов API), который зависит от результата нескольких других вызовов API (дочерних вызовов), но я не могу выполнить желаемое, так как результат дочерних вызовов не будет доступен в данный моментя делаю основной вызов API из-за асинхронного выполнения.

Вот мой код (что я пробовал) -

Сервисная функция Http -

async fetchShift(shiftName: string): Promise<any> {

const res = await this.httpClient.get(this.systemConfig.UIBACKEND_API_URL + '/api/v1/shift/find/' + shiftName).toPromise();
return res;
}

Промежуточная функция -

async formAssociateProduct(sheetAllRows): Promise<any> {

var promise = new Promise((resolve, reject) => {
  for (let i: number = 0; i < sheetAllRows.length; i++) {
    //Child api calls
    this.fetchShift("A").then(data => {
      this.listOfAssociatedProduct.push(data);
    });
  }
  resolve();
});
return promise;

}

ВызывающийФункция-

upload(event) {
console.log(event);
var me = this;
var reader = new FileReader();
var file = event.target.files[0];
reader.onload = function (event) {
  var workbook = XLSX.read(event.target.result, {
    type: 'binary'
  });

  var sheetAllRows = XLSX.utils.sheet_to_json(workbook.Sheets["Sheet1"]);
   me.formAssociateProduct(sheetAllRows).then(
    data => {
      //Main Api Call
      me.httpClient.post(me.systemConfig.UIBACKEND_API_URL + '/api/v1/products/upload', me.listOfAssociatedProduct).subscribe(data => {

      });
    }
  );  };

reader.readAsBinaryString(file);
}

Я нахожу список пустым в обратном вызове then (), необходимом для вызова Main api.Пожалуйста, помогите.

1 Ответ

0 голосов
/ 05 июля 2019

Здесь много проблем. Вот сводка изменений / комментариев:

  1. В formAssociateProduct() вы не дожидаетесь выполнения всех асинхронных вызовов, прежде чем разрешите возвращенное обещание. Я бы посоветовал использовать Promise.all(), чтобы отслеживать, когда они все будут готовы. И нет никакой пользы от функции async, так как вы не используете await. Вы можете просто вернуть обещание напрямую. При выполнении асинхронной обработки в массиве часто бывает проще использовать .map() и получить массив обещаний, которые затем можно передать Promise.all(), чтобы узнать, когда они все будут выполнены.

  2. fetchShift() похоже, что он будет работать так, как он есть, но опять же, нет причин для его пометки async, вы можете просто вернуть обещание напрямую.

  3. В upload() логика выглядит в основном правильной. Я переключился на функцию стрелки для обратного вызова, чтобы вы могли использовать this напрямую вместо me. Кроме того, похоже, что эта функция требует обработки ошибок в reader, при вызове formAssociateProduct() и при вызове основного API.

  4. Похоже, вы смешиваете обещания и обратный вызов из .subscribe() на самом низком уровне upload(). Как правило, это не очень хорошо, потому что трудно передать завершение, результаты и ошибки обратно вызывающей стороне. Я не знаю этих конкретных API-интерфейсов или точно знаю, чего вы пытаетесь достичь, чтобы точно знать, что предложить.

Вот исправленный код:

fetchShift(shiftName: string): Promise < any > {
    return this.httpClient.get(this.systemConfig.UIBACKEND_API_URL + '/api/v1/shift/find/' + shiftName).toPromise();
}

// call fetchShift on all the sheet rows
formAssociateProduct(sheetAllRows): Promise < any > {
    return Promise.all(sheetAllRows.map(row => {
        return this.fetchShift("A");
    })).then(results => {
        this.listOfAssociatedProduct = results;
    });
}

upload(event) {
    console.log(event);
    var reader = new FileReader();
    var file = event.target.files[0];
    reader.onload = (event) => {
        var workbook = XLSX.read(event.target.result, {
            type: 'binary'
        });

        var sheetAllRows = XLSX.utils.sheet_to_json(workbook.Sheets["Sheet1"]);
        // need lots of error handling here
        this.formAssociateProduct(sheetAllRows).then(data => {
            //Main Api Call
            return this.httpClient.post(me.systemConfig.UIBACKEND_API_URL + '/api/v1/products/upload',
                this.listOfAssociatedProduct).subscribe(data => {
                // some code here
            });
        });
    }
    // start reading the file
    reader.readAsBinaryString(file);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...