Создание рекурсивного цикла Observable? - PullRequest
0 голосов
/ 06 июня 2018

Мне трудно понять, как создать рекурсивный цикл для вызовов API с помощью Observables.

Сценарий: я вызываю внешний API, который возвращает что-то вроде этого:

{
 data: {something, something, something},
 next: "url for next set of data"
}

Мне нужно продолжать вызывать одну и ту же функцию, чтобы собрать все данные в один объект, пока ответ имеет значение в next.

Мне удалось сделать это в другом проекте с Promises, где я отображаюданные возвращаются в один массив с помощью функции concat(), но я почему-то не могу понять, как мне это сделать с Observables.

Рабочий пример с использованием обещаний:

getData: function(url, params, headers){
    return new Promise((resolve, reject) => {
        axios.get(url, {
            params: params,
            headers: headers,
        }).then((response) => {
            let responseData = response.data.data[0];
            if (response.data.next) {
                this.getData(response.data.next, {}).then((resp) => {
                    for (let dataSet of responseData.dataSets) {
                        let row = resp.dataSets.find(i => i.variable === dataSet.variable)
                        if (row) {
                            dataSet.data = dataSet.data.concat(row.data)
                        }
                    }
                    resolve(responseData);
                }).catch((error) => {
                    reject(error)
                })

            } else {
                resolve(responseData);
            }
        }).catch(error => {
            reject(error)
        })
    })
}

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Конечное решение, которое работало для меня:

let obs = this.getData(endpoint, options).pipe(
  expand(({ next }) => {
    // This could be oneliner but I had to alter options for the calls after the first one for my own case
    return next ? this.getData(next, options) : Observable.empty()
  }),
  concatMap(({data}) => data)
)

obs.subscribe(
  data => mapthedata(data),
  error => error,
  complete => {
    // do something with the mapped data
  }
)
function mapthedata(data) {
  // here you should combine the data results into one, f.ex pushing to local variable
}
0 голосов
/ 06 июня 2018

Вы можете использовать оператор .expand().Завершающим условием для этой рекурсии является свойство next, равное falsy.Используйте троичный оператор и код всего один вкладыш:

expand(({data, next}) => next ? getData(next): Observable.empty() )
    .subscribe(result => console.log(result));

Вот рабочая JSBin .Я издевался над несколькими вещами, но это должно быть довольно тривиально.

...