2015-10-14 4 views
2

Если у меня есть список предметов, входящих в Наблюдаемый из api, назовем их список «баров».Устранение наблюдаемых данных о свойствах наблюдаемого элемента

А теперь за каждые bar Мне нужно получить список связанных предметов - назовем их «foo» s. Вот что: api позволяет вам получить список foo s только при условии, если указан связанный код bar.

Так как это сделать? Должен ли я запускать отдельный запрос в subscribe | forEach? или, может быть, я мог бы создать поток URL-адресов и каким-то образом объединить их с потоком bars и сделать это именно так?

Вы можете создавать чудеса, используя Rx, применительно к материалам UI, к сожалению, мне сложно использовать его для работы с несколькими запросами ajax.

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

, например, если я пытаюсь сделать что-то вроде этого:

Rx.Observable.fromArray([ { bar:1 }, { bar:2 }, { bar:3 } ]) 
.map((x)=> { 
    x.foo = Rx.Observable.fromPromise(grabFoo(x)); 

    return x; 
}).subscribe((x)=> console.log(x)) 

это не будет работать. так как я могу сделать что-то подобное?

ответ

1

Я просто сделал это. Я использовал flatMap.

Вот отредактированная форма моего рабочего кода:

Обновлен с комментариями и используя панель и Foo и добавить listofbars()

// accumulates all bar s and foo s 
var data = {bars: [], errors: []}; 

// return observable of a foo 
var getFoo = function (Id, apiKey) { 
    return Rx.Observable.fromPromise($.ajax({ 
     method: "GET", 
     url: config.Uri + "/foos/" + Id, 
     headers: { "Authorization": "Bearer " + apiKey }, 
    })).share(); 
}; 
// return Observable of an array of bars 
var getBars = function (apiKey) { 
    return Rx.Observable.fromPromise($.ajax({ 
     method: "GET", 
     url: config.Uri + "/bars", 
     headers: { "Authorization": "Bearer " + apiKey }, 
    })).share(); 
}; 
// flatten Observable of an array of bar s to Observable of bar s 
var listOfBars = function (apiKey) { 
    return getBars(apiKey) 
    .flatMap(function (ep) { return (_a = Rx.Observable).of.apply(_a, ep); var _a; }); 
} 
// accumulate foos into data 
var getDataForFoo = function (data, bar, apiKey) { 
    return getFoo(bar.fooId, apiKey) 
    .map(function (foo) { 
     bar.foo = foo; 
     data.bars.push(bar); 
     return data; 
    }) 
    .catch(function (ex) { 
     data.errors.push({ name: { Id: Id, name: Name }, error: ex }); 
     return Rx.Observable.of(data); 
    }); 
}; 
var getDataForBars = function (data, apiKey) { 
    return listOfBars(apiKey) 
    .flatMap(function (bar) { return getDataForFoo(data, bar, apiKey); }) 
    .catch(function (ex) { 
     data.errors.push({ names: { Id: Id }, error: ex }); 
     return Rx.Observable.of(data); 
    }); 
}; 

Этот flatMap принимает массивы бару и выделяет каждый бар в отдельности.

.flatMap(function (ep) { return (_a = Rx.Observable).of.apply(_a, ep); var _a; }) 

Эта плоская карта берет каждый бар и делает новый веб-запрос, используя fooId из панели.

.flatMap(function (bar) { return getDataForFoo(data, bar, apiKey); }) 

Приведенный выше пример накапливает бары и foo s в модели данных. Кажется, вы просите поток бара, который содержит foo. С учетом вышеизложенного будет выглядеть так:

var barswithfoo = listOfBars(apiKey) 
    .flatMap(bar => { 
     return getFoo(bar.fooId, apiKey) 
      .map(foo => { 
       bar.foo = foo; 
       return bar; 
      }); 
    }) 
    .subscribe(); 

Вы можете видеть, что это похоже на ответ, который вы опубликовали. flatMap - карта + слияние. он ожидает, что карта вернет Observable и сразу же присоединяется к каждому наблюдаемому, который возвращается.

+0

вы можете объяснить, что здесь происходит? 'name',' names', 'dataForName',' dataForNames'. Я немного смущен. Что такое «точка входа» здесь? – Agzam

+0

не могли бы вы рассказать мне, что такое 'share()' зачем зачем вам нужно? – Agzam

+0

Несомненно. Имена - это набор объектов bar из вопроса, а каждое имя - объект foo. Точкой входа является getDataForNames, которая возвращает Observable, которая испускает данные var каждый раз, когда она изменяется (путем добавления имени или ошибки). Я использую это, чтобы обновить хранилище редукции, которое затем запускает компонент реакции для отображения набора имен. –

0

Таким образом, на самом деле сделать что-то вроде этой работы, я попытался это первое:

listOfbars.flatMap(x => 
    getFoo(x).then(r => { 
     x.foo = r; 
     return x; 
    }) 
) 
.subscribe(x => console.log(x)) 

он работает, хотя это мучительно медленно (потому что я предполагаю, что это решает все обещания только в конце), по сравнению с это:

listOfbars.flatMap(x => 
    Rx.Observable.fromPromise(getFoo(x)) 
    .map(r => { 
      x.foo = r; 
      return x; 
     }) 
) 
.subscribe(x => console.log(x)) 

похоже, что второй фрагмент не должен даже работать, surpisingly это

+0

да, второй - хороший перевод моего ответа, чтобы просто вернуть ea ch bar + foo вместо того, чтобы накапливать все бары в объект данных. Я обновил свой ответ, чтобы сделать это более ясным. –

Смежные вопросы