Angular - HTTP JSONP Method



The JSONP is a special technique (of feature) used to bypass the cross-domain (CORS) policies enforced by web browsers. Generally, browsers only support AJAX calls within the same domain. To make AJAX calls to another domain, CORS policies need to be enabled on both the server and the client (browser).

Instead of enabling the CORS policy, the server can send the response in JSONP format. JSONP format is JSON enclosed in a callback function. When the browser receives the response, it executes it as a script. The callback function then processes the response and performs the necessary business logic.

Syntax for the JSONP callback function −

mycallback({
    //...json data ...
});

Here,

  • mycallback is the name of the function sent by the browser (client).

In Angular, thejsonp()is the method available in theHttpClient service class used to request the server using the JSONP technique. It is similar to the HttpClient get()method with an additional option to set the name of the query parameter used to get the callback function by the server.

An Angular will auto-generate a function to parse the JSON on the client side. Then, it will add a new query parameter to the URL. The name of the query parameter will be the name set in the JSONP call. The value of the query parameter is the name of the function auto-generate by angular.

Signature of the jsonp() Method

The signature (different from syntax) of the HttpClient jsonp() method is as follows −

jsonp(url: string, callback: string): Observable<any>

Here,

  • url − The URL endpoint to which the JSONP request is made.
  • callback − It represents the callback function name (which will be auto-generated) to be invoked after the JSONP server call.
  • Observable<any> − The method returns an Observable that emits the JSONP response.

A simple code to demonstrate the JSONP method is as follows −

let jsonp_req = this.http.jsonp<Expense[]>
('http://localhost:8000/api/jsonp/expense', 'callback');

jsonp_req.subscribe(data => this.expenses = data);

Here,

  • The this.http is the HttpClient instance.
  • The jsonp()is a method used to request the server. It does not request the server directly. Instead, it returns an Observable, which can be used to request a server by subscribing to it and getting the actual response in the subscribed function.
  • The http://localhost/api/jsonp/expenseis the URI (Uniform resource identifier) of the resource.
  • Angular will auto-generate a function, sayng_jsonp_callback_0, and attach it to the request URL using the second argument of the jsonp() method.
http://localhost:8000/api/jsonp/expense?callback=ng_jsonp_callback_0

To work out the HTTP client-server communication, we need to set up a web application and need to exposes a set of web API. The web API can be requested from the client. Let us create a sample server application, Expense API App, and provide CRUD REST API (mainly JSONP requests) for expenses.

Create a Server for Expense REST API

Let's create a working angular application to put a resource into the above server application and then get all expense items from the server including the new resource by using the HttpClient service class.

Angular Sample Application

Step 1: Run the below command to create an angular application −

ng new my-http-app

Enable angular routing and CSS as shown below −

? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS

Step 2: Configure Http client

Let's learn how to configure the HttpClientservice. You need to import the HttpClient in App Config:

provideHttpClient(withInterceptorsFromDi())

app.config.ts

import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideBrowserGlobalErrorListeners(),
    provideRouter(routes),
    provideHttpClient(withInterceptorsFromDi())
  ]
};

Step 3: Create a new interface, Expense to show the expense items from the server −

interface Expense {
   id: Number,
   item: String,
   amount: Number,
   category: String,
   location: String,
   spendOn: Date
}

export default Expense;

Step 4: Create a new component, ListExpenses to show the expense items from the server −

ng generate component ListExpenses

It will create a new component as shown below −

CREATE src/app/list-expenses/list-expenses.css (0 bytes)
CREATE src/app/list-expenses/list-expenses.html (28 bytes)
CREATE src/app/list-expenses/list-expenses.spec.ts (602 bytes)
CREATE src/app/list-expenses/list-expenses.ts (229 bytes)

Step 5: Include our new component into the App root component view, app.component.html as shown below −

<app-list-expenses></app-list-expenses>
<router-outlet></router-outlet>

Step 6: Inject the HttpClient into the ListExpenses component through the constructor as shown below −

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
   selector: 'app-list-expenses',
   imports: [],
   templateUrl: './list-expenses.html',
   styleUrls: ['./list-expenses.css']
})
export class ListExpenses {

   constructor(private http: HttpClient) { }
}

Step 7: Implement the OnInit life cycle hook to request the server for expenses after the initialization of the ListExpenses component −

export class ListExpenses implements OnInit{
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
   
   }
}

Step 8: Create a local variable, expenses to hold our expenses from the server −

export class ListExpenses implements OnInit{
   expenses: Expense[] = [];   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
   
   }
}

Step 9 : Call the get() method of this.http (HttpClient instance) object by passing the URL & options and retrieving the expense object from the server. Then, set the expenses into our local variable, expenses −

export class ListExpenses implements OnInit{
   expenses: Expense[] = [];   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
   
   this.http.jsonp<Expense[]>
   ('http://localhost:8000/api/jsonp/expense','callback').subscribe(data =>{
         this.expenses = data as Expense[]
         console.log(this.expenses)
      })   
   }
}

Here,

  • Sets the Expense[] as the type of the object returned by the server. The server will send the array of expense objects in its body in JSON format.
  • Subscribed to the request (this.http.jsonp) object. Then parsed the subscribed data as an array of expense objects and set it to a local expense variable (this.expenses).

Step 10: The complete code of the ListExpenses is as follows −

list-expenses.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpRequest, HttpResponse, HttpEvent } from '@angular/common/http';
import Expense from '../Expense';

@Component({
   selector: 'app-list-expenses',
   templateUrl: './list-expenses.component.html',
   styleUrls: ['./list-expenses.component.css']
})
export class ListExpenses implements OnInit {
   expenses: Expense[] = [];   
   constructor(private http: HttpClient) { }
   
   ngOnInit(): void {
   
   this.http.jsonp<Expense[]>
   ('http://localhost:8000/api/jsonp/expense','callback').subscribe( data =>{
      this.expenses = data as Expense[]
      console.log(this.expenses)
      })      
   }
}

Step 11: Next, get the expenses object from the component and render it in our component template page (list-expenses.html) −

list-expenses.html

<div><h3>Expenses</h3></div>
<ul>
   @for(expense of expenses; track $index){
   <li>
      {{expense.item}} @ {{expense.location}} for {{expense.amount}} USD on {{expense.spendOn | date:'shortDate' }}
   </li>
   }
</ul>

Output

Step 12: Finally, run the application using the below command −

ng serve

Step 13: Open the browser and navigate to http://localhost:4200/ url and check the output

myhttpapp

Here, the output shows our expenses as a list of items.

Conclusion

Angular provides an easy way to request the server through the HttpClient object.jsonp() is a specific method used to get resources from the server even if the server does not support cross-domain API calls (CORS).

Advertisements