The result is not JSON
, but rather JSONP. It is essentially returning you a script that is trying to execute the callback method specified.
Instead of http.get()
you should call http.jsonp(url, "imbdIgnoresThisParam")
.
However, according to this answer, the callback
query string parameter is ignored by IMDB. The answer suggests dynamically creating the expected callback function, whose name contains the title for which you are searching. In that callback you could do a few different things.
- Use the closure to call / set something in your
MovieService
. This will result in your call to the API throwing an error, as the Angular framework's callback will not be called as expect. You could ignore the error.
- Try to call the expected Angular callback,
ng_jsonp_callback_<idx>
. This will prevent the API call from throwing, but it may not be reliable. The callback name is dynamic and increments with each jsonp()
call. You could try to track the number of jsonp()
calls in your app. And of course, the framework may change and break this solution. Concurrent calls to getMovie()
may break, as the next one may step on the previous callback on the window. Use with caution!
In typescript, your getMovie()
function and related helpers might look like so:
private imdbData: any = null;
private jsonpIdx = 0;
private setImdb(json: any) {
this.imdbData = json;
// or do whatever you need with this
}
getMovie(movie:string) {
// dynamically create the callback on the window.
let funcName = `imdb$${movie}`;
window[funcName] = (json: any) => {
// use the closure
this.setImdbData(json);
// or try to call the callback that Angular is expecting.
window[`ng_jsonp_callback_${this.jsonpIdx++}`](json);
}
// go get your data!
let url = this.generateURL(movie)
return this.http.jsonp(url, "ignored").subscribe((json) => {
// this happens if you successfully trigger the angular callback
console.log(json);
}, (err) => {
// this happens if the angular callback isn't called
console.log(this.imdbData); // set in closure!
});
}
Edit for Angular 4
For Angular 4
, it looks like you will need to import the JsonpModule
along with the HttpModule
. Then, you'd inject jsonp
just like you'd inject http
into your service. The call to IMDB becomes this.jsop.request(url).subscribe(...)
and your dynamic callback name needs to change, too.
window[funcName] = (json: any) => {
// or try to call the callback that Angular is expecting.
window["__ng_jsonp__"][`__req${this.jsonpIdx++}`]["finished"](json);
}
I don't have an Angular 5 or 6 project immediately set up, so hard to say if there are any differences with the callback in those versions.
Sort of a hack, but hope it helps!