JavaScript Async, AJAX, and JSONP - Handling Asynchronous Operations
JavaScript is single-threaded but excels at handling asynchronous operations. This post covers the essential concepts of async programming in JavaScript.
Understanding Asynchronous JavaScript
JavaScript is single-threaded, meaning there’s no way to truly block execution. Instead, we use callbacks, Promises, and async/await for handling asynchronous operations.
Async/Await (ES2017+)
The async and await keywords provide a cleaner way to work with Promises.
Basic Async Function
An async function automatically wraps its return value in a Promise:
async function f() {
return 1;
}
f().then(alert); // 1
This is equivalent to:
async function f() {
return Promise.resolve(1);
}
f().then(alert); // 1
Await Keyword
Use await to pause execution until a Promise resolves:
async function asyncCall() {
console.log('calling');
var result = await resolveAfter2Seconds();
console.log(result); // "resolved"
}
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
asyncCall();
Immediately Invoked Async Function
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
})();
Wait/Sleep Function
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
Promises
Promises represent the eventual result of an asynchronous operation.
Creating a Promise
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
AJAX (Asynchronous JavaScript And XML)
AJAX allows you to update parts of a web page without reloading the entire page.
Basic AJAX with XMLHttpRequest
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
// readyState 4 = response is ready
// status 200 = OK
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
}
POST Request with Headers
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "ajax_url", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=Henry&lname=Ford");
Reusable AJAX Function
function loadDoc(url, callback) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
callback(this);
}
};
xhttp.open("GET", url, true);
xhttp.send();
}
function myFunction(xhttp) {
document.getElementById("demo").innerHTML = xhttp.responseText;
}
// Usage
loadDoc('ajax_info.txt', myFunction);
XMLHttpRequest Methods
| Method | Description |
|---|---|
open(method, url, async, user, psw) |
Configures the request |
send() |
Sends the request (GET) |
send(string) |
Sends the request with data (POST) |
setRequestHeader(header, value) |
Sets HTTP header |
abort() |
Cancels the request |
XMLHttpRequest Properties
onreadystatechange- Event handler for state changesreadyState- Current state (0-4)status- HTTP status coderesponseText- Response as textresponseXML- Response as XML
Older Browser Support (IE5/IE6)
var xmlhttp;
if (window.XMLHttpRequest) {
// Modern browsers
xmlhttp = new XMLHttpRequest();
} else {
// Old IE browsers
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
JSONP (JSON with Padding)
JSONP is a technique for making cross-domain requests, which AJAX cannot do due to same-origin policy.
How JSONP Works
JSONP uses the <script> tag instead of XMLHttpRequest:
<script src="demo_jsonp.php"></script>
Server returns JavaScript that calls a predefined function:
<?php
$myJSON = '{ "name":"John", "age":30, "city":"New York" }';
echo "myFunc(" . $myJSON . ");";
?>
When loaded, this executes myFunc with the JSON data as a parameter.
Dynamic JSONP Request
function clickButton() {
var script = document.createElement("script");
var data = { "table": "products", "limit": 10 };
script.src = "demo_jsonp.php?x=" + JSON.stringify(data);
document.body.appendChild(script);
}
function myFunc(data) {
// Handle the response
console.log(data);
}
JSON Operations
Parsing and Stringifying
// JSON string to object
var obj = JSON.parse('{"name":"John","age":30}');
// Object to JSON string
var json = JSON.stringify({name: "John", age: 30});
Custom Parser
Handle special types like dates during parsing:
var text = '{"name":"John","birth":"1985-01-15"}';
var obj = JSON.parse(text, function(key, value) {
if (key == "birth") {
return new Date(value);
}
return value;
});
Adding Functions to Parsed JSON
var text = '{ "name":"John", "age":"function() {return 30;}" }';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");
console.log(obj.age()); // 30
Warning: Using
eval()is dangerous and should be avoided with untrusted data.
Security Considerations
Same-Origin Policy
AJAX requests are restricted to the same domain for security reasons. To make cross-domain requests, you need:
- CORS (Cross-Origin Resource Sharing) - Server-side configuration
- JSONP - For GET requests only
- Proxy - Server-side proxy on your domain
Understanding asynchronous JavaScript is essential for building modern web applications. These patterns allow you to create responsive, non-blocking user interfaces.
Comments