3

I'm pretty new to the whole Cycle.js/RxJS ecosystem and was hoping for someone to guide me on the process of aborting an ongoing ajax call since it looks like doable somehow.

It would be awesome to have a little example forked from the search-github-user one using this.

I'm adding here a copy from that example for the sake of avoiding SO zealots downvoting:

import Cycle from '@cycle/core';
import {Observable} from 'rx';
import {div, label, input, hr, ul, li, a, makeDOMDriver} from '@cycle/dom';
import {makeHTTPDriver} from '@cycle/http';

function main(sources) {
  // Requests for Github repositories happen when the input field changes,
  // debounced by 500ms, ignoring empty input field.
  const searchRequest$ = sources.DOM.select('.field').events('input')
    .debounce(500)
    .map(ev => ev.target.value)
    .filter(query => query.length > 0)
    .map(q => ({
      url: 'https://api.github.com/search/repositories?q=' + encodeURI(q),
      category: 'github',
    }));

  // Requests unrelated to the Github search. This is to demonstrate
  // how filtering for the HTTP response category is necessary.
  const otherRequest$ = Observable.interval(1000).take(2)
    .map(() => 'http://www.google.com');

  // Convert the stream of HTTP responses to virtual DOM elements.
  const vtree$ = sources.HTTP
    .filter(res$ => res$.request.category === 'github')
    .flatMap(x => x)
    .map(res => res.body.items)
    .startWith([])
    .map(results =>
      div([
        label({className: 'label'}, 'Search:'),
        input({className: 'field', attributes: {type: 'text'}}),
        hr(),
        ul({className: 'search-results'}, results.map(result =>
          li({className: 'search-result'}, [
            a({href: result.html_url}, result.name)
          ])
        ))
      ])
    );

  const request$ = searchRequest$.merge(otherRequest$);

  return {
    DOM: vtree$,
    HTTP: request$
  };
}

Cycle.run(main, {
  DOM: makeDOMDriver('#main-container'),
  HTTP: makeHTTPDriver()
});

UPDATE

Thanks to @user3743222 for pointing out the change on the master branch, it seems that the author has released a new version and now the abort part is here.

user3743222
  • 18,345
  • 5
  • 69
  • 75
coma
  • 16,429
  • 4
  • 51
  • 76

2 Answers2

1

I am not familiar at all with the new code, but in the old code it seems like the http driver returns an observable for each request made. If that observable terminates/is unsubscribed before the request is fulfilled, that request is aborted. So basically, call the API, get the observable encapsulating the request results, and terminate that observable when you want to abort.

How to terminate an observable at will? You could probably use takeUntil(someOtherStream) if you have another stream signaling abort.

user3743222
  • 18,345
  • 5
  • 69
  • 75
  • Try to figure it out by yourself. It is a good exercise. Otherwise, I would guess that somebody (else) will give you a more detailed answer. I am short time and I don't have an example at hand. I only answered because two days have passed since you asked. You could also review the https://github.com/staltz/flux-challenge. The cyclejs solution is used for cancelling requests. – user3743222 Jun 28 '16 at 21:26
  • @coma `takeUntil` (or the current cyclejs version [`endWhen`](https://github.com/staltz/xstream#endWhen)) ends the stream permanently, cannot make more requests. Do you want that? Or do you just want to cancel the last request, and be able to make more requests? – bloodyKnuckles Jun 29 '16 at 13:24
  • @bloodyKnuckles, the second one, watch the network console tab: http://s.codepen.io/comakai/debug/JYbdzj – coma Jun 29 '16 at 13:29
1

In current version, all the response$ streams get listened to immediately, so they never terminate before the request comes and aborting doesn't work effectively. There's an issue on that.

Philipp Ryabchun
  • 736
  • 1
  • 5
  • 7