3

We have an Angular app. It uses Http from @angular/http.

For easier development of services and functionality not related to UI, I'd like to use something else for HTTP requests, since using Angular's brings in a lot of dependencies and needs a special environment (a running Angular app).

I've tried jQuery's $.ajax() but that one does not return a normal Promise but some JQueryPromise which is not compatible with ES5 Promise.

Is there some library which returns ES2015 Promise, or better, RxJs's Observable?

Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
  • 3
    jQuery 3.0+ is Promises/A+ compatible – adeneo Oct 20 '16 at 14:50
  • 3
    And I don't think there are any promises in ES5, promises was added in ES2015 – adeneo Oct 20 '16 at 14:52
  • you say "we have an angular app", then you say "I'd like to use something for HTTP requests since ... " (so you wanna keep Angular and just replace a part of it or get rid of it completely?) then you say You want to have a method/library that returns a ES5 promise and then you say better "Observable" . (Observable brings in a shitload of dependencies as well btw.) could you clarify? – George Katsanos Oct 20 '16 at 16:28
  • Fixed the ES2015. Explained why not Angular's Http. – Ondra Žižka Oct 21 '16 at 02:53

4 Answers4

3

This answer deals with Promises.

jQuery 3+

jQuery 3 Promises are Promises/A+ compatible, so they don't need converting; they are already compatible with native Promises.

Older jQuery versions

A+ Promises can wrap any thenable object, like $.Deferred, so converting to an ES6 Promise is trivial:

const legitPromise = Promise.resolve($.ajax({ /* ... */ }))

Promise.resolve on MDN

joews
  • 29,767
  • 10
  • 79
  • 91
0

You could wrap jQuery's ajax request with your own function that returns RxJs's observable:

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
const jQuery = require('jquery');

/**
 * Function to call in place of jQuery.ajax(...).
 */
export const ajax = function(options: any) : Observable<any> {

  // Init a new observable subject.
  const subject = new Subject<any>();

  // Make the ajax call.
  jQuery.ajax(Object.assign({}, options, { complete, error, success }));

  // Return the subject as an observable.
  return subject.asObservable();

  /**
   * Fires when jQuery's request calls its `complete` callback.
   */
  function complete(xhr: any, textStatus: string) : void {
    subject.complete({ xhr, textStatus });
  }

  /**
   * Fires when jQuery's request calls its `error` callback.
   */
  function error(xhr: any, textStatus: string, errorThrown: string) : void {
    subject.error({ xhr, textStatus, errorThrown });
  }

  /**
   * Fires when jQuery's request calls its `success` callback.
   */
  function success(data: any, textStatus: string, xhr: any) : void {
    subject.next({ data, textStatus, xhr });
  }

}
ryannjohnson
  • 373
  • 1
  • 5
  • 13
0

Use RxJS with jQuery:

var observable = Rx.Observable.fromEvent(
    $(document),
    'mousemove');

var subscription = observable.subscribe(function (e) {
    $('#results').text(e.clientX + ',' + e.clientY);
});

// or a normal ajax call
function searchWikipedia (term) {
    var promise = $.ajax({
        url: 'http://en.wikipedia.org/w/api.php',
        dataType: 'jsonp',
        data: {
            action: 'opensearch',
            format: 'json',
            search: encodeURI(term)
        }
    }).promise();
    return Rx.Observable.fromPromise(promise);
}

$('#input').toObservable('keyup')
    .map(function (e) { return e.target.value; })
    .flatMapLatest(searchWikipedia)
    .subscribe(function (data) {

        var results = data[1];

        $.each(results, function (_, result) {
            // Do something with each result
        });

    });
<input id="input" type="text"/>
<div id="results"></div>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.async.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.binding.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
George Katsanos
  • 13,524
  • 16
  • 62
  • 98
0

My colleague found that RxJS actually has this right in Observable:

import {Observable} from 'rxjs/Observable';
Observable.ajax.getJSON(url).subscribe(...);
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277