2016-11-22 5 views
0

Ich baue einen infinite Scroller in cycle.js. Ich habe einen Ajax-Service, der X-Ergebnisse pro Seite liefert. Die erste Anforderung hat eine Seiten-ID von 0, nachfolgende Anforderungen müssen jedoch die in der ersten Ergebnismenge zurückgegebene Seiten-ID verwenden. Die Ergebnisse werden im Dom platziert. Wenn der Benutzer zum Ende der sichtbaren Ergebnisse scrollt, wird ein neuer Satz geladen und mit der Liste verkettet. Ich habe etwas, das funktioniert, aber nicht so gut, wie ich es möchte.Cycle.js streamen Zusammensetzung, um einzelne AJAX-Anfragen zu gewährleisten

Die verkürzte Version wie folgt aussieht:

const onScroll$ = sources.DOM.select('document').events('scroll') 
 
    .map((e) => { 
 
     return e.srcElement.scrollingElement.scrollTop; 
 
    }) 
 
    .compose(debounce(1000)); 
 

 
    const onHeight$ = sources.DOM.select('#items').elements() 
 
    .map((e) => { 
 
     return e[0].scrollHeight; 
 
    }) 
 

 
    const scroll$ = onScroll$.startWith(0); 
 
    const height$ = onHeight$.startWith(0); 
 

 
    const itemsXHR$ = sources.HTTP.select('items') 
 
    .flatten(); 
 

 
    const id$ = itemsXHR$ 
 
    .map(res => res.body.data.content.listPageId) 
 
    .take(2) 
 
    .startWith(0); 
 

 
    const getitems$ = xs.combine(scroll$,height$,id$) 
 
    .map(([scrollHeight, contentHeight, sid, lp]) => { 
 
     if (scrollHeight > (contentHeight - window.innerHeight - 1)) { 
 
     const ms = new Date().getTime(); 
 
     return { 
 
      url: `data/${sid}?_dc=${ms}`, 
 
      category: 'items', 
 
      method: 'GET' 
 
     }; 
 
     } 
 
     return {}; 
 
    }); 
 

 
    const items$ = itemsXHR$ 
 
    .fold((acc=[],t) => [...acc, ...t.body.data.content.items]) 
 
    .startWith(null); 
 

 
    const vdom$ = items$.map(items => 
 
    div('#items', [ 
 
     ul('.search-results', items==null ? [] : items.map(data => 
 
     li('.search-result', [ 
 
      a({attrs: {href: `/${data.id}`}}, [ 
 
      img({attrs: {src: data.url}}) 
 
      ]) 
 
     ]) 
 
    )) 
 
    ]) 
 
);

Das Hauptproblem ist, dass die Ajax-Request Position zu bewegen ist, verbunden ist, und dessen möglich, dass während des Scroll mehrere Anfragen zu feuern.

Als der Moment entprell ich die Scroll, aber das ist es nicht ideal hier.

Haben Sie Ideen, wie Sie die Streams so orchestrieren, dass nur eine Anforderung gesendet wird, wenn sie benötigt wird (wenn sich der Benutzer am Ende der Seite befindet)?

Ich könnte vielleicht eine eindeutige ID pro Seite und verwenden .dropRepeats auf dem getitem $? Ich habe jedoch keine eindeutige Seiten-ID im Ergebnis.

Antwort

0

Sie könnten die Rolle $ filtern, um nur den unteren Rand der Seite zu nehmen.

const onScroll$ = sources.DOM.select('document').events('scroll') 
.map((e) => { 
    return e.srcElement.scrollingElement.scrollTop; 
}) 
.filter(/* filter by checking scrollTop is near bottom */) 
.compose(debounce(1000)); 
Verwandte Themen