Как перезапустить или обновить Observable?

8

У меня есть TypeScript/Angular 2 Observable, который отлично работает в первый раз, когда я его вызываю. Тем не менее, я заинтересован в подключении нескольких подписчиков к тем же наблюдаемым и каким-то образом освежающим наблюдаемым и прикрепленным подписчикам. Вот что у меня есть:

query(): Rx.Observable<any> {

return this.server.get('http://localhost/rawData.json').toRx().concatMap(
    result =>
        result.json().posts
    )
    .map((post: any) => {
        var refinedPost = new RefinedPost();
        refinedPost.Message = post.Message.toLowerCase();

        return refinedPost;

    }).toArray();

}

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

Как я могу это сделать?

Теги:
angular
rxjs

1 ответ

4
Лучший ответ

Я не так много знаю о Angular2 и Typescript, но typescript является надмножеством javascript, я сделал следующую гипотезу (дайте мне знать, если я ошибаюсь), которая должна сделать следующий код javascript работа:

  • server.get возвращает обещание (или массив или Rx.Observable)
  • posts - это массив post

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

// get the DOM id for the button
var button = document.getElementById('#xxx');

// create the observable of refined posts
var query$ = 
    Rx.Observable.fromEvent(button, 'click')
        .flapMapLatest(function (ev) {
                     return this.server.get('http://localhost/rawData.json')
                   })
        .map(function (result){return result.json().posts})
        .map(function (posts) {
                return posts.map(function(post){
                                   var refinedPost = new RefinedPost();
                                   refinedPost.Message = post.Message.toLowerCase();
                                   return refinedPost;
                           })
             })
        .share()

// subscribe to the query$. Its output is an array of refinedPost
// All subscriptions will see the same data (hot source)
var subscriber = query$.subscribe(function(refinedPosts){console.log(refinedPosts)})

Некоторое объяснение:

  • Каждый клик вызывает вызов server.get, который возвращает тип совместимого с наблюдаемым (массив, обещание или наблюдаемый). Это возвращаемое наблюдаемое сглажено, чтобы извлечь result из этого вызова
  • Поскольку пользователь может щелкнуть много раз, и каждый клик генерирует поток данных, и нас интересует (другая гипотеза, которую я здесь делаю) только в результате последнего щелчка, мы используем оператор flatMapLatest, который будет выполнять flatMap только на наблюдаемом, сгенерированном последним кликом
  • Мы извлекаем массив post posts и делаем из него массив refinedPost. В конце каждого щелчка будет создан массив refinedPost, который я предполагаю, что вы хотите
  • Мы разделяем это наблюдение, поскольку вы упоминаете, что у вас будет несколько подписчиков, и вы хотите, чтобы все подписчики увидели одни и те же данные.

Сообщите мне, правильны ли мои гипотезы и если это сработало для вас.

Кроме того, я рекомендую вам взглянуть на https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

В дополнение к тому, чтобы быть очень хорошим напоминанием о концепциях, он решает проблему вызова сервера обновления, очень похожую на вашу.

  • 0
    Спасибо за ответ. Это хорошо, но есть предположение, что я не уверен в том, что я непосредственно фиксирую нажатие кнопки. В действительности обработчик нажатия кнопки находится в другом классе, чем наблюдаемая работа. Я хотел иметь возможность запустить обновление наблюдаемого с помощью только вызова функции. FWIW, я был в состоянии сделать то, что я хотел с предметом, но я подумал, есть ли способ сделать это с «прямой»
  • 0
    Да, вы можете заменить Rx.Observable.fromEvent(button, 'click') вашей темой. Иногда вы можете использовать Rx.Observable.create вместо субъекта, обернуть в него создание слушателя и вернуть одноразовое устройство, чтобы удалить слушателя - но, не видя ваш код, я не знаю, возможно ли это или нет. Рад, что это сработало. Нет ничего плохого в использовании темы, когда нет лучшего варианта, например, когда у вас нет / нет источника события в области видимости. Кстати, некоторые рекомендации SO: если ответ хорош для вас, вы должны принять его.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню