admin管理员组

文章数量:1023738

Using Rxjs v5, trying to run http.get requests in sequential order but getting error TypeError: promise.then is not a function js code:

    var http = require('http');
    Rx.Observable
        .from(data)
        .pairwise()
        .concatMap(a => {
            var url = 'http://to/some/api?origins=' + a[0].lat + ',' + a[0].lng + '&destinations=' + a[1].lat + ',' + a[1].lng;
            return Rx.Observable.fromPromise(http.get(url));        
        })    
        .subscribe(item => {
            console.log(item);
        });

Using Rxjs v5, trying to run http.get requests in sequential order but getting error TypeError: promise.then is not a function js code:

    var http = require('http');
    Rx.Observable
        .from(data)
        .pairwise()
        .concatMap(a => {
            var url = 'http://to/some/api?origins=' + a[0].lat + ',' + a[0].lng + '&destinations=' + a[1].lat + ',' + a[1].lng;
            return Rx.Observable.fromPromise(http.get(url));        
        })    
        .subscribe(item => {
            console.log(item);
        });
Share Improve this question asked Aug 10, 2016 at 16:57 coure2011coure2011 42.6k87 gold badges225 silver badges361 bronze badges 5
  • 1 http.get doesn't return a Promise. It returns an event handler. – Mike Cluck Commented Aug 10, 2016 at 16:59
  • so any alternate method? – coure2011 Commented Aug 10, 2016 at 17:33
  • 1 You don't need the wrapper of fromPromise just return http.get(url) directly. – paulpdaniels Commented Aug 10, 2016 at 18:00
  • return http.get(url) directly throws another error TypeError: unknown type returned – coure2011 Commented Aug 11, 2016 at 9:09
  • Nvm, I didn't realize that the node http.get method follows some odd semantics, see my answer below. – paulpdaniels Commented Aug 12, 2016 at 5:05
Add a ment  | 

1 Answer 1

Reset to default 2

The node http.get method does not return a promise, see here

It actually uses a rather non-standard interface (at least I haven't really seen it before), so to get this working you need a small custom work-around instead (note: this is a relatively naive implementation):

var http = require('http');
function observableGet(options) {
  return new Rx.Observable(subscriber => {
    var subscription = new Rx.Subscription();

    //Create the request
    var request = http.get(options, (res) => {
      //Create a stream for the "end" event
      var done = Rx.Observable.fromEvent(res, 'end');

      //Create a stream for data events
      var s1 = Rx.Observable.fromEvent(res, 'data')
        //Take data events until all have been read
        .takeUntil(done)
        //Gather all the data events into a single object
        .reduce((body, delta) => body + delta, '')
        //Optional: Parse the resulting data object
        .map(x => JSON.parse(x))
        //Start the stream
        .subscribe(subscriber);

      //Register this stream for disposal
      subscription.add(s1);
    });

    //Grab errors from the request and forward them to the error handler
    //of subscriber
    var s2 = Rx.Observable.fromEvent(request, 'error', (e) => { throw e; })
      .subscribe(subscriber);

    //Register for disposal
    subscription.add(s2);

    //Return the parent subscription
    return subscription;
  });
}

Then you can use it in place of http.get

    Rx.Observable
    .from(data)
    .pairwise()
    .concatMap(a => {
        var url = //...url;
        return observableGet(url);        
    })    
    .subscribe(item => {
        console.log(item);
    });

Alternatively you could use a library that returns Promises instead, which might make your life easier, i.e. request-promise

Using Rxjs v5, trying to run http.get requests in sequential order but getting error TypeError: promise.then is not a function js code:

    var http = require('http');
    Rx.Observable
        .from(data)
        .pairwise()
        .concatMap(a => {
            var url = 'http://to/some/api?origins=' + a[0].lat + ',' + a[0].lng + '&destinations=' + a[1].lat + ',' + a[1].lng;
            return Rx.Observable.fromPromise(http.get(url));        
        })    
        .subscribe(item => {
            console.log(item);
        });

Using Rxjs v5, trying to run http.get requests in sequential order but getting error TypeError: promise.then is not a function js code:

    var http = require('http');
    Rx.Observable
        .from(data)
        .pairwise()
        .concatMap(a => {
            var url = 'http://to/some/api?origins=' + a[0].lat + ',' + a[0].lng + '&destinations=' + a[1].lat + ',' + a[1].lng;
            return Rx.Observable.fromPromise(http.get(url));        
        })    
        .subscribe(item => {
            console.log(item);
        });
Share Improve this question asked Aug 10, 2016 at 16:57 coure2011coure2011 42.6k87 gold badges225 silver badges361 bronze badges 5
  • 1 http.get doesn't return a Promise. It returns an event handler. – Mike Cluck Commented Aug 10, 2016 at 16:59
  • so any alternate method? – coure2011 Commented Aug 10, 2016 at 17:33
  • 1 You don't need the wrapper of fromPromise just return http.get(url) directly. – paulpdaniels Commented Aug 10, 2016 at 18:00
  • return http.get(url) directly throws another error TypeError: unknown type returned – coure2011 Commented Aug 11, 2016 at 9:09
  • Nvm, I didn't realize that the node http.get method follows some odd semantics, see my answer below. – paulpdaniels Commented Aug 12, 2016 at 5:05
Add a ment  | 

1 Answer 1

Reset to default 2

The node http.get method does not return a promise, see here

It actually uses a rather non-standard interface (at least I haven't really seen it before), so to get this working you need a small custom work-around instead (note: this is a relatively naive implementation):

var http = require('http');
function observableGet(options) {
  return new Rx.Observable(subscriber => {
    var subscription = new Rx.Subscription();

    //Create the request
    var request = http.get(options, (res) => {
      //Create a stream for the "end" event
      var done = Rx.Observable.fromEvent(res, 'end');

      //Create a stream for data events
      var s1 = Rx.Observable.fromEvent(res, 'data')
        //Take data events until all have been read
        .takeUntil(done)
        //Gather all the data events into a single object
        .reduce((body, delta) => body + delta, '')
        //Optional: Parse the resulting data object
        .map(x => JSON.parse(x))
        //Start the stream
        .subscribe(subscriber);

      //Register this stream for disposal
      subscription.add(s1);
    });

    //Grab errors from the request and forward them to the error handler
    //of subscriber
    var s2 = Rx.Observable.fromEvent(request, 'error', (e) => { throw e; })
      .subscribe(subscriber);

    //Register for disposal
    subscription.add(s2);

    //Return the parent subscription
    return subscription;
  });
}

Then you can use it in place of http.get

    Rx.Observable
    .from(data)
    .pairwise()
    .concatMap(a => {
        var url = //...url;
        return observableGet(url);        
    })    
    .subscribe(item => {
        console.log(item);
    });

Alternatively you could use a library that returns Promises instead, which might make your life easier, i.e. request-promise

本文标签: javascriptTypeError promisethen is not a functionStack Overflow