Как выполнить обратный вызов вложенного javascript обещания библиотеки внутри вызова angular rx js subscribe - PullRequest
0 голосов
/ 10 июля 2020

У меня есть требование всякий раз, когда возникает ошибка, мне нужно собирать базовую c трассировку ошибок, IP-адрес и снимок экрана.

Для IP-адреса я использую этот API для получения IP-адреса. getIp: 'http://api.ipify.org/?format=json'. Для ScreenShot с использованием Html2 Canvas: library: https://github.com/niklasvh/html2canvas/issues/2282.

Это метод срабатывает при возникновении ошибки.

Я добавил await, но он не ждет ответа от обратного вызова, он вернется раньше выполняется обратный вызов.

первоначальный вызов

getIP(response:any)
  {
// call 1
    this.getIPAddress().subscribe(async(res:any)=>{ 
    this.ipAddress = res.ip;  
// get an ip once ip recieved call another function


    let errorRequest =  await this.logError(response); call 2
// another service call
    this.logErrorRequest(errorRequest); //  send another service call to server to store the error
    });

    return  errorDetails;
  } 

второй вызов .. в этом методе форматируйте запрос. Здесь для скриншота мне нужно вызвать javascript библиотеку html2canvas. await this.getScreenShot ()

// проблема в том, что метод вернет ответ до получения ответа от этого вызова обещания.

async logError(response:any):ErrorRequest{
    error={
        ExceptionMessage:response.message,
        ipAddress:this.ipAddress,
        screenShot:await this.getScreenShot()    // next call 3.
    };
   
    return error;
}

// обратный вызов обещания

async getScreenShot() {
    this.zone.runOutsideAngular(() => {
// call 4
      html2canvas(document.querySelector("#capture")).then(canvas => {
      canvas.toBlob(function(blob){
                let link = document.createElement("a");
                link.download = "image.png";
                link.href = URL.createObjectURL(blob);
                link.click();
                let screenShot = blob; 
                 this.screenShot = blob;

            },'image/png');

   
         //your code
      })   

    });

1 Ответ

0 голосов
/ 10 июля 2020

Вы не возвращаете ничего из своего getScreenShot(), кроме Promise<void>, но это только из-за async. Также кажется, что первые 2 вызова не зависят друг от друга, поэтому вы можете выполнять их параллельно:

Это означает, что, чтобы просто исправить вашу проблему, вам нужно реорганизовать свой getScreenShot() метод:

getScreenShot() {
  return this.zone.runOutsideAngular(async () => {
    const canvas = await html2canvas(document.getElementById("capture"));

    return new Promise(
      (resolve) => canvas.toBlob((blob) => resolve(blob), 'image/png')
    );
  });
}

Короче говоря, верните вызов this.zone, дождитесь вызова html2canvas, создайте новое обещание и верните его в своем решении. Также не используйте ключевое слово function, потому что это испортит контекст this.

Более длительное исправление, которое потребует рефакторинга вашего кода, будет выглядеть примерно так:

logError(response: { message: string }): void {
  forkJoin([
    this.getIPAddress(),
    this.getScreenShot()
  ]).pipe(
    concatMap(([ { ip }, screenshot ]) => this.logErrorRequest({
      ExceptionMessage: response.message,
      ipAddress: ip,
      screenshot
    }))
  ).subscribe({
    next: () => console.log('error logged'),
    error: () => console.log('make sure to catch this to prevent loop!')
  });
}

Очевидно, здесь будет использован рефакторинговый метод getScreenShot. Как вы могли заметить, это намного яснее и позволяет избежать случайных назначений this. Это хороший поток, точно так же, как rx js хочет чего-то.

Также убедитесь, что вы каким-то образом отклоняете / группируете журнал ошибок, чтобы предотвратить переполнение или бесконечное l oop ошибок. зарегистрирован. Поверьте, бывает: D

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...