Angular 2 JSONP injected script did not invoke callback error - javascript

I am running app on localhost://3000 with npm server
Services file:
import {Injectable} from "#angular/core";
import {Jsonp} from "#angular/http";
import 'rxjs/add/operator/map';
#Injectable()
export class futScoreService{
constructor(private _jsonp:Jsonp){}
getCompetitions(){
let queryString ='?callback=JSONP_CALLBACK';
return this._jsonp.get('http://api.football-data.org/v1/competitions/' + queryString,{method: 'Get'})
.map((res) => res.json());
}
}
Component file:
ngOnInit(){
this._futScoreService.getCompetitions().subscribe(
(comp)=>{
console.log(comp);
},
(err)=>{
console.log(err);
}
);
}
And I'm getting this error in console console-error
and on network tab I get object from API network-tab

Ok solution was making get request with http module and providing header with get request. Header part was main reason why it was failing.
let headers = new Headers({'X-Mashape-Key':'Ns0SkjyRRomshq3PgEnGoz2Zkc71p1CYnWajsnphGctvrGt46W'});
headers.append( 'Accept', 'application/json');
return this._http.get("http://api.football-data.org/v1/competitions/",{
headers: headers
})
.map((res) => res.json());

Angular is replacing JSONP_CALLBACK with
__ng_jsonp____req0_finished
but it should be
__ng_jsonp__.__req0.finished
Inspect your Network response. If you see __ng_jsonp____req0_finished({...json object...}) this is the problem.
Also, some services have different requirements for the callback query string parameter, which proves to be nasty because the error is exactly the same. I was using &callback=__ng_jsonp__.__req0.finished with MailChimp which produced the same error but the response had only a json object and no callback function. This is because MailChimp's spec is to use &c= instead of &callback=
When hardcoding the Jsonp callback (re: JSONP_CALLBACK issue) you need to account for the number of calls made, as Angular persists the state of each call. An example of what I'm doing for Mailchimp:
addEmailToList(email: string, listId: string, jsonpCalls: number, callback: any) {
const cbJsonp = '__ng_jsonp__.__req' + jsonpCalls + '.finished';
let url = [
'http://',
host,
'/subscribe',
'/post-json',
].join('');
let queryParams: URLSearchParams = new URLSearchParams();
queryParams.set('u', Config.MAILCHIMP_API_KEY);
queryParams.set('id', listId);
queryParams.set('EMAIL', email);
queryParams.set('c', cbJsonp); // non-standard; varies by service; usually 'callback'
...
}

this._InstUrl = "your url";
let params1 = new URLSearchParams();
//params.set('search', term); // the user's search value
//params.set('action', 'opensearch');
params1.set('format', 'json');
//params1.set('callback', "ng_jsonp.__req0.finished");
params1.set('callback', "JSONP_CALLBACK");
return this._jsonp
.get(this._InstUrl, { search: params1 })
.map(response => { debugger; this.Result = response.json().data })
.subscribe(
(data) => {
debugger
console.log(this.Result);
},
(error) => {
debugger
console.log(error);
});

Related

Axios client with useSwr Fails to make request

Im using a shared Axios "client" object that is passed around my application via react context, this client object has the API key auth header and base paths already configured so im not constantly defining it.
My problem is trying to use the useSwr hook, specifically when defining the fetcher. I just cannot get it to work, and im sure im missing something simple here.
Basically, I pull the api client off the context, and use a fetcher function iv defined already, but I get nothing.
Here's some snips,
The Client
const AXIOS_CLIENT_CONFIG = {
baseURL: API_BASE,
timeout: 2000,
};
export default class APIClient {
client: AxiosInstance;
accessToken: string;
headers: any;
constructor(accessToken?: string) {
this.accessToken = accessToken;
this.headers = { Authorization: `Bearer ${accessToken}` };
if (accessToken) {
this.client = axios.create({
...AXIOS_CLIENT_CONFIG,
headers: this.headers,
});
} else {
this.client = axios.create(AXIOS_CLIENT_CONFIG);
}
}
fetcher(url: string): Promise<any> {
return this.client.get(url).then((res) => res.data);
}
The Component
export default function Upload(): ReactElement {
const { api }: IAppContext = useContext(AppContext);
const { data, error } = useSwr(`/upload/${uploadId}`, api.fetcher, {
refreshInterval: 5000,
});
Using above, I see nothing, no requests, no errors. (yes, the client comes through fine, I use this throughbout my whole app, its just this fetcher part that is broken)
Just for testing if I define the following fetcher, I can see a request is made (and failed due to auth)
const fetcher = (url) => axios.get(url).then((res) => res.data);
Even logging out the function signatures, they look almost the same to me
console.log("API FETCHER", api.fetcher);
console.log("NORMAL FETCHER", fetcher);
Outputs
API FETCHER ƒ fetcher(url) {
return this.client.get(url).then(function (res) {
return res.data;
});
}
NORMAL FETCHER ƒ fetcher(url) {
return axios__WEBPACK_IMPORTED_MODULE_5___default().get(url).then(function (res) {
return res.data;
});
}
What am I doing wrong here?
After hours of screwing around, I eventually figured this out. Incase anyone else comes across the issue when trying to use an Axios client objection with class functions like I am here.
I had no bound the context of this within the class for that specific function.
Basically, I needed to add the following to my api clients constructor
// Bind "this" context
this.fetcher = this.fetcher.bind(this);

Error while subscribing from http request angular

I'm working on the test driven angular app. (Don't ask why, That is how client wants)
Below is the spec which I can't modify or edit.
it('should get results', fakeAsync(
inject(
[XHRBackend, NewsService ],
(mockBackend: MockBackend, newsService: NewsService) => {
const expectedUrl = 'https://api.nytimes.com/svc/topstories/v2/home.json?api-key=315a5a51483b469a918246dc2753b339';
mockBackend.connections.subscribe((connection : MockConnection) => {
expect(connection.request.method).toBe(RequestMethod.Get);
expect(connection.request.url).toBe(expectedUrl);
connection.mockRespond(new Response(
new ResponseOptions({ body: mockResponse })
));
});
newsService.getSectionNews('home')
.subscribe( (res: any) => {
expect(res).toEqual(mockResponse);
});
})
));
So based on the spec, I need to write my front end code.
So this is what I've written,
import { Http } from '#angular/http';
constructor(private http: Http) {}
getSectionNews(sectionName: string): any {
// fetch news of that sectionName
// return this.mockResponse;
const expectedUrl = 'https://api.nytimes.com/svc/topstories/v2/home.json?api-key=315a5a51483b469a918246dc2753b339';
return this.http.get(expectedUrl).subscribe(res => res);
}
But while running the test case, I'm getting this error:
TypeError: newsService.getSectionNews(...).subscribe is not a function
please tell me what I'm doing wrong here.
I wanted to pass the test case.
UPDATE
After updating my service spec.
getSectionNews(sectionName: string): Observable<any> {
const expectedUrl = `https://api.nytimes.com/svc/topstories/v2/${sectionName}.json?api-key=315a5a51483b469a918246dc2753b339`;
return this.http.get(expectedUrl);
}
Now I'm getting this below error,
Expected Response with status: null null for URL: null to equal
Objectt({ status: 'OK', copyright: 'C ...

Cannot make a simple http GET call in Angular2

I am trying to make a simple http GET request from my Angular2 app:
this.http.get("https://mybaseurl.com/hello")
.map(res => res.json())
.subscribe(
function(response) { console.log("Success Response" + response)},
function(error) { console.log("Error happened" + error)},
function() { console.log("the subscription is completed")}
);
The Node.js server is configured this way:
app.get('/hello', function(req, res) {
res.send("hellow world");
});
When I make the call I keep getting this error:
caused by: unable to parse url 'https://mybaseurl.com/hello'; original error: Cannot read property 'split' of undefined
at InMemoryBackendService.parseUrl (in-memory-backend.service.ts:518)
at InMemoryBackendService.handleRequest (in-memory-backend.service.ts:279)
at InMemoryBackendService.createConnection (in-memory-backend.service.ts:240)
Any idea what am I doing wrong?
edit: pasting the entire class code:
import {Component} from '#angular/core';
import {Auth} from './auth.service';
import {AuthHttp} from 'angular2-jwt';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'ping',
templateUrl: 'app/ping.template.html'
})
export class ApiService {
API_URL: string = 'https://myapp.herokuapp.com';
message: string;
constructor(private auth: Auth, private http: Http, private authHttp: AuthHttp) {}
public ping() {
this.http.get(`${this.API_URL}/hello`)
.map(res => res.json())
.subscribe((response) => {
console.log("Success Response" + response)
},
(error) => { console.log("Error happened" + error)},
() => { console.log("the subscription is completed")}
);
}
}
=====>
This looks like a HUGE bug in Angular2 - all http requests return null, or an error message describing it is not in the required pattern.
I someone has a working demo of HTTP GET I would love to see
It looks like using InMemoryWebApiModule.forRoot(InMemoryDataService) in #NgModule simultaneously with Http.get causes uncovered urls to return null and error.
Setting it this way worked for me:
InMemoryWebApiModule.forRoot(InMemoryDataService, {passThruUnknownUrl: true})
Maybe it is beacause of your answer from server - you send string to client, but in map function you try to call res.json(). Can you comment map function call?
Check by using arrow function for success and error as below :
this.http.get("https://mybaseurl.com/hello")
.map(res => res.json())
.subscribe((response) => { console.log("Success Response" + response)},
(error) => { console.log("Error happened" + error)},
() => { console.log("the subscription is completed")}
);

Angular 2 HTTP GET to Node backend for list of file names in directory

I'm trying to use an Angular 2 HTTP GET request to simply connect with a Node/Express backend that responds with a list of the file names in a certain folder using the fs.readdir method.
I set up the Angular 2 request as a service:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import './rxjs-operators';
#Injectable()
export class PhotoService {
constructor (private http: Http) {}
private photosUrl = '/api/photos'; // URL to web API
getPhotos() : Observable<string[]> {
return this.http.get(this.photosUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
}
and then called this service from a component:
ngOnInit() {
this.photoService.getPhotos()
.subscribe(
photos => this.fileList = photos,
error => this.errorMessage = <any>error);
}
This is the Node backend (with Express set up as per conventions):
//Photo Service
app.get('/api/photos', function(req, res) {
fs.readdir('./uploads', function(error, files) {
if (error) {
throw error;
}
else {
res.end(files);
}
});
});
As seen, the HTTP request calls a GET method to http://localhost:3000/api/photos and the Node backend is supposed to receive that request and send back an array of strings that have the names of files in the 'uploads' folder.
However it does not seem to be working. I think I'm getting confused with the format in which the Node API sends the response and how that works with the Observable type that Angular uses in the service.
Your Angular 2 code looks good to me. But in your Node backend you should not send data with res.end() (see the documentation). Correct would be res.send(files); or in your case res.json(files); which will also set the right Content-Type header.

Angular 2 http many subscribers

I have a Page and a Service in Angular 2.
When i call the service function this.Auth.login(), it makes a http post request. My problem is, that as soon as the request returns data, i want to work with that data in the service AND the page.
I tried all kinds of stuff, but couldn't figure out how to do it.
I know that my code can't work like this because right now this.Auth.login() return a subscriber object. If i remove the '.subscribe()' in the service, it works in the Page. But thats not what i need.
I also tried to return a promise, but couldn't make it work either.
Does anybody know how i can achieve to have the data from the http.post in both controllers and work with it as soon as the request is finished?
Here's my code
Page:
import {AuthService} from '../auth/auth.service';
#Page({
templateUrl: 'build/pages/signin/signin.html'
})
export class Signin {
constructor(app: IonicApp, auth: AuthService){
this.Auth = auth;
}
signIn = function() {
this.Auth.login(this.user.email, this.user.password)
.subscribe(data => {do some stuff here});
// maybe a promise with .then can solve this
};
}
Service:
import {Http, Headers} from 'angular2/http';
import {Injectable} from 'angular2/core';
#Injectable()
export class AuthService {
private http;
constructor(http:Http) {
this.http = http;
}
login(email, password) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
// maybe i need to return this as a promise
return this.http.post('http://localhost:9000/auth/local', JSON.stringify({
email: email,
password: password
}), {
headers: headers
})
.subscribe(data => {
do some stuff here too with the data
));
// i tried to add .toPromise() but that didn't work
}
}
I left out the other lines of code so there might be some dependencies missing. It's all good though.
You can use map in the body of the Service login. i.e
.map(data => {
do some stuff here too with the data
// still bubble up
return data;
));
Ok, i don't know if this is legit but it seems to work for me:
var res = this.http.post('http://localhost:9000/auth/local', JSON.stringify({
email: email,
password: password
}), {
headers: headers
});
res.subscribe(
data => {
console.log('data');
},
err => {
console.log('err');
},
() => {
console.log('next');
}
);
return res;

Categories