AJAX (Asynchronous JavaScript and XML) is a methodology for enabling asynchronous communication between web pages and servers without full page reloads. It leverages browser APIs like XMLHttpRequest (XHR) or the modern Fetch API too exchange data in the background, then dynamically updates specific page sections using JavaScript. Historically XML was the primary data format, but JSON is now standard due to its lightweight nature and JavaScript compatibility.
XMLHttpRequest (XHR) Implementation
Download Progress Tracking
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-button @click="startDownload">Initiate Download</el-button>
<el-button @click="cancelDownload">Cancel Download</el-button>
<el-progress type="circle" :percentage="downloadProgress"></el-progress>
</div>
</body>
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
const request = new XMLHttpRequest();
new Vue({
el: '#app',
data: {
downloadProgress: 0
},
methods: {
startDownload() {
request.addEventListener('progress', event => {
this.downloadProgress = Number(((event.loaded / event.total) * 100).toFixed(2));
});
request.open('GET', 'https://example.com/sample-data.zip');
request.send();
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log('Download complete:', request.responseText);
}
};
},
cancelDownload() {
request.abort();
}
}
});
</script>
</html>
Upload Progress Tracking
To track upload progress, replace the download listener with an upload event listener:
request.upload.addEventListener('progress', event => {
this.uploadProgress = Number(((event.loaded / event.total) * 100).toFixed(2));
});
Fetch API Implementation
Fetch is promise-based and lacks direct progress events, but we can track download progres by reading the response body incrementally using a ReadableStream.
Download Progress Tracking
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-button @click="startDownload">Initiate Download</el-button>
<el-button @click="cancelDownload">Cancel Download</el-button>
<el-progress type="circle" :percentage="downloadProgress"></el-progress>
</div>
</body>
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
const controller = new AbortController();
const signal = controller.signal;
new Vue({
el: '#app',
data: {
downloadProgress: 0
},
methods: {
async startDownload() {
const response = await fetch('https://example.com/sample-data.zip', {
method: 'GET',
signal
});
const totalSize = Number(response.headers.get('content-length'));
const decoder = new TextDecoder();
let accumulatedContent = '';
const reader = response.body.getReader();
let loadedBytes = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
loadedBytes += value.length;
accumulatedContent += decoder.decode(value);
this.downloadProgress = Number(((loadedBytes / totalSize) * 100).toFixed(2));
}
console.log('Download complete:', accumulatedContent);
},
cancelDownload() {
controller.abort();
}
}
});
</script>
</html>
Upload Progress Tracking
Currently, the Fetch API does not support native upload progress tracking. For a temporary solution, you could implement a simulated progress indicator.