получить значение из объекта Observable <value> - PullRequest
0 голосов
/ 30 августа 2018

Я пишу сервисную функцию, где она должна отвечать за последнюю цену продукта. Я подключаюсь к своему серверу, используя websocket, и получаю DataStream, используя наблюдаемый Rxjs, теперь предполагается, что функция в слое службы отвечает только на значение, а не на объект Observable.

Пример кода, который я пытаюсь

public getRealTimePrice(id: string): number {

 let ws = new $WebSocket('/price?Id=' + id + '&connectionId=' + this.randomUUID());
    this.priceWebsocket = ws;

    this.priceWebsocket.getDataStream()
      .map(msg => JSON.parse(msg.data).price)
      .subscribe(responseNumber => {
        return responseNumber // by the time execution reaches here the context is changed.
      });
    // I am not returning anything on the function level - which results in a compilation error as per typescript.
  }

но по очевидной причине я не могу вернуть номер - так как он находится внутри обратного вызова подписки, где меняется контекст и функция асинхронна

Как я могу ждать ответа от Observable и затем возвращать только значение, полученное в Observable.

Ответы [ 4 ]

0 голосов
/ 31 августа 2018

Я не уверен в возможности ожидания Angular, но, глядя на документацию, похоже, что это будет примерно так:

public getRealTimePrice(id: string): Promise<number> {

    let ws = new $WebSocket('/price?Id=' + id + '&connectionId=' + this.randomUUID());
    this.priceWebsocket = ws;

    this.priceWebsocket.getDataStream()
      .map(msg => JSON.parse(msg.data).price)
      .subscribe(responseNumber => {
        return responseNumber
      })
      .take(1)
      .toPromise();
}

Затем вы можете вызвать его, используя ключевое слово await:

async getAsyncValue(id: string) {
    const value = <number>await this.getRealTimePrice(id);
    console.log(`number: ${value}`);
}

Обратите внимание, что перед функцией стоит ключевое слово "async", это необходимо, если в функции есть ключевое слово "await".

Ключевое слово "async" будет означать, что console.log не будет выполняться, пока обещание от функции "getRealTimePrice ()" не будет разрешено (или отклонено).

0 голосов
/ 30 августа 2018

В идеале вы должны вернуть Observable из вызова getDataStream () в методе getRealTimePrice и выполнить подписку в том месте, где ожидаются данные.

0 голосов
/ 30 августа 2018

Я бы предложил использовать toPromise так:

public getRealTimePrice(id: string): Promise<number> {
    let ws = new $WebSocket('/price?Id=' + id + '&connectionId=' + this.randomUUID());
    this.priceWebsocket = ws;

    return this.priceWebsocket.getDataStream()
        .map(msg => JSON.parse(msg.data).price)
        .take(1)
        .toPromise()
}

Примечание * Оператор take(1), который примет первое значение и отменит подписку на DataStream.

0 голосов
/ 30 августа 2018

Единственный реальный способ сделать это - вернуть обещание. Поскольку вызов асинхронный, вы не сможете вернуть только значение. Примерно так будет работать:

public getRealTimePrice(id: string): Promise<number> {
    return new Promise((resolve, reject) => {
        let ws = new $WebSocket('/price?Id=' + id + '&connectionId=' + this.randomUUID());
        this.priceWebsocket = ws;

        this.priceWebsocket.getDataStream()
        .map(msg => JSON.parse(msg.data).price)
        .subscribe(responseNumber => {
            resolve(responseNumber);
        });
    });
}

Тогда вы можете назвать это так:

getRealTimePrice().then((data:number) = {
    console.log(data);
});
...