Как дождаться окончания http.get в угловых - PullRequest
0 голосов
/ 13 февраля 2019

Я пытался добавить значения в мой массив data, однако я столкнулся с проблемой, что он переходит к data.push() раньше, чем возвращается значение из функции getValue.Я пытался это исправить, но не смог придумать решение и почувствовать себя здесь немного потерянным.

Это функция, где я формирую данные:

formData() {
  for (const id of Object.keys(this.cols)) {
    let p= cols[id];
    switch (p.name) {
      case 'a':
      this.temp.name= this.addValue(m, p);
        break;
      case 'b':
        let idx = 1;
        let surname= this.getValue(idx);
        break;
    }
  }
  this.data.push(this.temp);
});

иВот как выглядит моя функция getValue:

 getValue(id: string) {
let url = this.baseUrl + '/streams/' + id+ '/data?';
url += 'from=' + from + '&';
url += 'to=' + to;
this.http.get(url).map(r => r.json()).subscribe((response: any) => {
        if (response.data.values[0] !== null && response.data.values[0] !== undefined) {
         return response.data.values[0];
        }
}, (error: any) => {
    return null;
});

как мне избежать передачи данных в массив до того, как это значение будет на самом деле?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Если бы это был менее сложный вопрос, я бы полностью поддержал закрытие этого вопроса как дубликата, но, как говорится в моем комментарии к вопросу, это немного сложнее.

Для начала вам следуетОбязательно прочитайте об асинхронных функциях и о том, как использовать ответы от них.Далее, вы, как правило, должны стараться избегать использования асинхронной функции внутри цикла, поскольку их сложно прогнозировать и контролировать.К счастью, есть способы заставить асинхронные функции вести себя более синхронно.

Обратите внимание на следующее:

async formData(): Promise<void> {
  for (const id of Object.keys(this.cols)) {
    let p= cols[id];
    switch (p.name) {
      case 'a':
      this.temp.name= this.addValue(m, p);
        break;
      case 'b':
        let idx = 1;
        let surname = await this.getValue(idx);
        break;
    }
  }
  this.data.push(this.temp);
});

getValue(id: string): Promise<string> {
    return new Promise(resolve => {
        let url = this.baseUrl + '/streams/' + id+ '/data?';
        url += 'from=' + from + '&';
        url += 'to=' + to;
        this.http.get(url).map(r => r.json()).subscribe((response: any) => {
            if (response.data.values[0] !== null && response.data.values[0] !== undefined) {
                resolve(response.data.values[0]);
            }
        }, (error: any) => {
            resolve(null);
        });
    });
}

Ваш вызов getValue является асинхронным, поскольку требует задержки (вызов на сервер), прежде чем значение можно будет вернутьЯ обернул это в Promise, так как вы хотели, чтобы пути успеха и ошибки подписки возвращали значение.

Если мы пометим метод formData ключевым словом async, которое мы теперь можем использоватьключевое слово await в методе.Это заставит поток метода ожидать возврата из обещания getValue, прежде чем управление продолжится.

Side-not: помечая метод formData асинхронным, он возвращает тип возвратаметод a Promise, даже если вы ничего напрямую не возвращаете из метода.

0 голосов
/ 13 февраля 2019

как мне избежать передачи данных в массив до того, как это значение будет на самом деле?

зацепить его от подписки, например:

this.http.get(url).map(r => r.json()).subscribe((response: any) => {
        if (response.data.values[0] !== null && response.data.values[0] !== undefined) {
         // NOTE
         this.loadFormData();
        }
...