2017-02-16 3 views
0

저는 반응 형 프로그래밍을 처음 접했고 짧은 코드 스 니펫에 대한 의견을 듣고 Rx 사고 방식에서 얼마나 멀리 떨어져 있는지보고 싶습니다.코드 검토 : 다음 rxjs 원칙입니까?

제 목적은 한 번에 최대 500 개 항목을 반환하는 웹 서비스에서 약 2245 개의 항목을 가져 오는 것입니다. 그래서 여러 번 전화를 걸어 모든 결과를 연결해야합니다.

$ .getJSON에서 반환 한 모든 약속을 배열에 저장 한 다음 forkJoin 메서드를 사용하여 결과를 모두 처리합니다.

// get the exact total number of items 
function getCount() { 
    return $.get({ 
     url: '/sites/_api/items/count', 
     contentType: "application/json;odata=verbose", 
     headers: { "Accept": "application/json;odata=verbose" } 
    }); 
} 

getCount().done(function (result) { 
    var promises = []; // store promises 
    var total = result.d.ItemCount; // total number of items 
    var batch = 500; // number of items to fetch for each request 
    var count = Math.ceil(total/batch); // number of request needed 

    for (var i = 0; i < count; i++) { 
     var skip = batch * i; // number of item already fetched 
     var top = batch * (i + 1) > total ? (total % batch) : batch; // number of item to fetch 
     var p = $.getJSON("/sites/_api/items?$select=" + fieldname + "&$skip=" + skip + "&$top=" + top); // get promise 
     promises.push(p); // store promise in dedicated array 
    } 

    // join all promises and handle all results at once 
    Rx.Observable.forkJoin(promises).subscribe(function (result) { 
     console.log(result); //[object, object, object, object, object] 
    }); 

}); 

이렇게하면 예상되는 결과가 나오지만 Rx를 사용하여 더 좋은 방법이 있다면 의견을 듣고 싶습니다.

------ EDIT --------- 스트림 개념을 기반으로 한 첫 번째 시도 코드를 추가합니다. 의미 나는 알 수없는 번호의 요청을합니다. 그들이 온 것처럼 결과를 더할 것이고 (onDataReceived 함수를 보라), 끝날 때 결과를 전체적으로 다룰 것이다. 나는 모든 요청이 완료되었음을 알리는 방법을 발견 할 수 없었고 관찰 가능 항목의 '완료된'방법을 시작했다.

var items = []; 
 
var obs; 
 

 

 
function onDataReceived(data) { 
 
    obs.onNext(data); 
 
} 
 

 
function getFieldValue(fieldname, skip, top) { 
 
    var uri = "/sites/_api/items?&$skip=" + skip + "&$top=" + top; 
 
    $.getJSON(uri, onDataReceived); 
 
} 
 

 
function getCount() { 
 
    return $.get({ 
 
     url: '/sites/_api/items/count', 
 
     contentType: "application/json;odata=verbose", 
 
     headers: { "Accept": "application/json;odata=verbose" } 
 
    }); 
 
} 
 

 

 
    
 
obs = new Rx.Subject(); 
 

 
obs.subscribe(
 
    function (value) { items = items.concat(value.d); }, 
 
    function (err) { console.err(err); }, 
 
    function() { console.log("completed" + items.length); } 
 
); 
 

 

 
getCount().done(function (result) { 
 
    var total = result.d.ItemCount;  
 
    var batch = 500; 
 
    var count = Math.ceil(total/batch); 
 
    for (var i = 0; i < count; i++) { 
 
     var skip = batch * i; 
 
     var top = batch * (i + 1) > total ? (total % batch) - 1 : batch; 
 
     getFieldValue(skip, top); 
 
    } 
 
});

+5

가 나는 http://codereview.stackexchange.com/에 답변 –

답변

0

코드는 수신이 제공하는 모든 혜택을 복용하지 않고 단순히 관찰 가능한 자사의 인터페이스를 변화하고 있습니다. 그것은 여전히 ​​내부적으로 약속되어 있습니다.

약속은 열심이므로 $_json()을 호출하면 즉시 데이터를 가져옵니다. 적어도 당신의 코드 또는 축소 가능한 푸시 많은 약속은 기능에 대한 API (10 개 동시 요청을 조절 포함 예를 구현 아래 참조를 실행하는 경우에만시 .subscribe 시작 게으른 관찰 가능한을 반환 할 Rx.Observable.defer()

시도로 포장하는 경우 페이지 세부 사항)

function mock_get_count() { 
 
    return Rx.Observable.of(255) 
 
    .delay(500) 
 
    .toPromise(); // to mock $.get() signature (returning promise) 
 
} 
 

 
function mock_get_page(page) { 
 
    return Rx.Observable.of('') 
 
    .do(() => console.log('starting page ' + page)) 
 
    .ignoreElements() 
 
    .concat(
 
     Rx.Observable.range(10 * page, 10) 
 
     .toArray() 
 
     .delay(1000 + Math.random() * 2000) /* slow api, response takes 1-3 seconds*/ 
 
    ) 
 
    .toPromise() /* to mock your $.JSON() signature (returning promise) */ 
 
    ; 
 
} 
 

 
function getAllResults() { 
 
    return Rx.Observable.defer(() => mock_get_count()) 
 
    .mergeMap(itemCount => { 
 
     const pages = Math.ceil(itemCount/10); 
 
     console.log('itemCount: ' + itemCount + ', pages: ' + pages); 
 
    
 
     return Rx.Observable.range(0, pages) 
 
     .mergeMap(
 
      p => Rx.Observable.defer(() => mock_get_page(p)), 
 
      null, 
 
      10 /* concurrent requests to API */ 
 
     ); 
 
    }) 
 
} 
 

 
getAllResults().subscribe(console.log) 
 
      
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.1.0/Rx.js"></script>

+0

감사를 속하기 때문에 오프 주제로이 질문을 닫습니다 투표를하고있다. 나는이 요청을 어쨌든해야하기 때문에 이것이 나에게 정말로 중요한 문제는 아니지만, 느린 로딩의 이점을 이해합니다. 내 관심사는 내가 알 수없는 요청 수가 많아서 모두 완료되면 결과를 전체적으로 처리해야합니다. RxJS로 방향을 돌 렸는데 실제로이 스트림을 볼 수 있기 때문입니다. 원본 요청을 편집하여 스트림 "패턴"을 기반으로 한 첫 번째 시도 코드를 추가했습니다. 요청을 완료 한 방법을 알아 채지 못하고 관찰 가능 항목의 "완료된"메서드가 트리거되었습니다. – Julien

+0

안녕 줄리앙, 문제의 Rx 버전으로 수정 된 답변을 참조하십시오. 지연로드는 정확히 ** 알 수없는 요청 수가 있기 때문에 필요한 항목입니다 **. 그것들을 조절해야합니다. Rx를 사용하여 결과를 스트리밍 할 수 있습니다. –