0

I'm using a service(force.ts) for performing CRUD operation in my angular2 app. Service's API returns a promise which is converted as Observable in the DataService(internal service written to communicate / modify data to/from ForceService).

If the records are beyond 2,000 or response size is larger, Salesforce RestAPI service automatically send the fewer records and it sends out the nextRecordsUrl property to fetch next batch of records.

As I get the record from the DataService, I wanted to update the view gradually. I tried but the result is not properly returning properly.

Here's is the intended flow:

1: call getAccounts()

2: return the result, update the view

2.1: if nextRecordsUrl is present, call getNextBatchOfAccounts()

2.1.1: repeat from step 2

Here's the code I tried :

import { Injectable } from '@angular/core';
import { ForceService } from '../force';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class DataService {


    getAccounts() {
        let promise =  this.force.query(
           'SELECT Id,Name FROM Account'


        let self = this;

        return Observable.fromPromise(promise).map(result => {
            let data = (<any>result).records;

            if(result.nextRecordsUrl) {
                return getNextBatchOfAccounts(result.nextRecordsUrl.slice(27));
            }
            else {
                return data.map(function(record) {
                    return self._convertToCustomType(record);
                })
            }

        });
    }

    getNextBatchOfAccounts(queryId) {
        let promise =  this.force.getNextUrlRecords(
           queryId
        );

        return Observable.fromPromise(promise).map(result => {
            let data = (<any>result).records;

            if(result.nextRecordsUrl) {
                return getNextBatchOfAccounts(result.nextRecordsUrl.slice(27));
            } else {
                return data.map(function(record) {
                    return self._convertToCustomType(record);
                })
            }

        });

    }

    _convertToCustomType(item:any) {
        return {
            'label' : item.Name,
            'value' : item.Id
        };
    }
} 
Praveen
  • 85
  • 1
  • 12
  • 3
    I guess that there is already answer to your question, see https://stackoverflow.com/questions/35254323/rxjs-observable-pagination/35494766#35494766 – Oles Savluk Oct 08 '17 at 20:55
  • @OlesSavluk Your solution worked for me. Thank you very much. I have a question so as to how the subscriber of the Observable gets record one by one. Reason it in my case, the API returns an array of object but somehow the subscriber gets object one by one(looks like it is being resulted is iterated and it's invoking the subscriber's callback)? – Praveen Oct 18 '17 at 17:28
  • It is done by `Observable.fromArray(items);`. You can replace it with `.of` to get stream of arrays – Oles Savluk Oct 18 '17 at 19:25

1 Answers1

0

Maybe use a pattern like the following

 step1().switchMap(res=>{
  if(res.nextRecordsUrl) 
    return step2().repeat().takeWhile(v=>res.nextRecordsUrl)
  return Observable.of(res)
}).subscribe()
Fan Cheung
  • 10,745
  • 3
  • 17
  • 39