Check out a free preview of the full Asynchronous Programming in JavaScript (with Rx.js Observables) course

The "JSONP as an Observable" Lesson is part of the full, Asynchronous Programming in JavaScript (with Rx.js Observables) course featured in this preview video. Here's what you'd learn in this lesson:

Now that Jafar has a working JSONP call, he converts it into an Observable. This creates the forEach and dispose functions required for subscribing to the Observable. When JSON data is received, the Observable calls the onNext and onCompleted.


Transcript from the "JSONP as an Observable" Lesson

>> [MUSIC]

>> Jafar: So how can we take this and turn it into an observable, so that instead of when we call search Wikipedia and immediately make new network requests, we want it to return an observable to us, which will on next us this array and then complete and then tell us it's done.

So an observable of one, in other words. So, we're going to show you how to create an observable, just gonna keep running files come into those. So whenever you wanna take an existing API and adapt it into an observable, we're gonna call this getWikipediaSearchResults. Remember that an observable is an object with only one method, the forEach method.

Right, and there's a helper function, which will return an observable. Actually, I'm gonna write it the long way, and then we're gonna convert it into the way that we saw before. So I'm gonna have a forEach method in here. And remember that that forEach method accepts an observer, which is three methods, on next, on error, and on completed.

That's the observer, that's the thing that we're sending information to. So in here, I'm actually gonna make this call to get JSON, the jQuery API.
>> Jafar: And inside of this code, instead of a learning, all I'm gonna do is send this information, in this case, I'm actually gonna just pull out data at one, which is the array of search results, to the observer.

Now at this point, we know we're never gonna call the observer ever again. Right, cuz the way jQuery API works, the JSON API just goes to the server, gets one thing, and then it finishes. So we wanna tell the consumer, hey, look, we're never gonna call you again.

And so we just tell them onCompleted, and that's how we create an observable with only one element in it. Now remember that we also have to return something else. Can anybody tell me what it is, when I forEach over an observable what has to be returned?
>> Speaker 2: A dispose.

>> Jafar: A subscription object with a dispose method on it, right? Because if I forEach over this observable, and half like a second later, maybe the network request taking a really long time, and I decide, I don't want that network request results. I need some way of cancelling that.

So we're gonna return an object with a dispose method. And in here, we have to sort of somehow cancel the request if possible. Now the interesting thing about this is that it's not really possible to cancel this request, and you're gonna come across this all the time. Most synchronous APIs don't have one of these four semantics that observable has.

The ability to deliver a value, the ability to deliver an error, the ability to say onCompleted, and the ability for the consumer to say, I don't want anymore data, those are the four semantics of an observable. But most asynchronous APIs only have maybe two or three or one.

And so jQuery API, the JSONP API is an example of where, well, they don't really have the notion of cancel. If you think about what's happening under the hood, it's actually adding a script tag with a source that points to that URL, and then that code is gonna get run, it's gonna get call our callback, whether we want the data or not.

And so sometimes when the underlying asynchronous API doesn't support the semantics of the observable, you have to fake it. So, in this case, we just wanna make sure that if somebody calls dispose on our subscription, we never call them. And so that means we need to remember that somebody's called dispose.

So, I'm gonna create a cancelled boolean, I'm gonna set it to false. And then inside of dispose, I'm gonna set canceled to true. Now inside of my callback, I'm gonna set an if condition that says, if not cancelled. So while I can't cancel the underlying requests, and you'll run across this all the time where async APIs don't provide you this flexibility.

At the very least, you can avoid, you can satisfy the observable contract by making sure that if somebody dispose of a subscription, we don't call them. Now, if we were using an XHR instead of a JSONP, we could actually call XHR abort, and we should probably do that instead, so that we cancel that network request.

Does that make sense? So now we've got an API that'll give us an observable if we ask for it, an observable that triggers a network request, and we've got an observable stream of all the key presses. So let's see if we can build something like it out of complete box.

So but now that I've written it this out the long way, I wanna show you that the real correct way of doing this is that observable has a helper function called create. And because we know that an observable is only one for each method, we can just shorten it.

So Observable.create just takes the definition of forEach.
>> Jafar: So we don't need to create that object.
>> Jafar: And the same thing here, instead of the same ceremony of always creating an object with a dispose method, we'll just return the function that we used to dispose. And that just allows you to write less code, cuz that part's always gonna be the same, every single time you create an observable.

So now we've got, hopefully, something we can call get WikipediaSearchResults.
>> Jafar: And let's pass in Terminator.
>> Jafar: So if I run this, what would we expect to happen right now?
>> Speaker 3: Nothing, it's just returning an observable, and you're not even storing it in a variable.
>> Jafar: Right, just creating an observable does nothing because observables are lazy.

We've got a forEach over this observable in order to call that for each method write up here and cause it to do something. So let's call forEach, and that's passing a function,
>> Jafar: And let's alert them.
>> Jafar: So if we run this,
>> Jafar: Great, so now we've done the same thing, except now we have an observable API.

So now we get to do the fun stuff, which is compose these things together using map, filter, concatAll, etc.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now