Skip to content

Instantly share code, notes, and snippets.

@ve3
Last active June 17, 2021 16:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ve3/203fa29e9461d84abab9728beea8846b to your computer and use it in GitHub Desktop.
Save ve3/203fa29e9461d84abab9728beea8846b to your computer and use it in GitHub Desktop.
Ajax (XHR) with max concurrent connection.
<!--demo1-max-concurrent-wait-all.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>XHR multi concurrent connection</title>
<style>
#debug {
border: 3px dashed #ccc;
margin: 10px 0;
padding: 10px;
}
</style>
</head>
<body>
<form id="upload-form" method="post">
<input type="hidden" name="hidden-name" value="hidden-value (unnecessary)">
<button type="submit">Submit</button>
<div id="debug"></div>
</form>
<script src="xhr.js"></script>
<script type="application/javascript">
let debugElement = document.getElementById('debug');
const thisForm = document.getElementById('upload-form');
const maxConcurrentConnection = 3;
thisForm.addEventListener('submit', (event) => {
event.preventDefault();
let loopPromise = Promise.resolve();
let ajaxCons = [];
for (let i = 0; i < 10; i++) {
loopPromise = loopPromise.then(() => {
if (ajaxCons.length < maxConcurrentConnection) {
debugElement.insertAdjacentHTML('beforeend', '<p>Calling to server round '+ i + '. (number from JavaScript.)</p>');
ajaxCons.push(
XHR('server.php?round=' + i)
.then((responseObject) => {
const response = responseObject.response;
debugElement.insertAdjacentHTML('beforeend', '<p> &nbsp; &gt; Response from server: Round: <code>' + response.round + '</code></p>');
return Promise.resolve();
})
.catch((responseObject) => {
console.warn('response: ', responseObject);
debugElement.insertAdjacentHTML('beforeend', '<p style="color: red;"> &nbsp; &gt; Error! see console.</p>');
return Promise.reject();
})
.finally(() => {
})
);
if ((parseInt(ajaxCons.length)) === parseInt(maxConcurrentConnection)) {
return new Promise((resolve, reject) => {
Promise.all(ajaxCons)
.then((value) => {
console.log('value', value);
ajaxCons = [];
resolve();
});
});
}
}
});
}
/*
// basic example loop make ajax call and wait until finish then next loop...
let loopPromise = Promise.resolve();
for (let i = 0; i < 10; i++) {
loopPromise = loopPromise.then(() => {
console.log('round ' + i);
return new Promise((resolve, reject) => {
XHR('server.php?round=' + i)
.then((responseObject) => {
const response = responseObject.response;
console.log('response: ', response);
resolve();
})
.catch((responseObject) => {
console.warn('response: ', responseObject);
reject();
});
});
});
}
*/
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>XHR multi concurrent connection</title>
<style>
#debug {
border: 3px dashed #ccc;
margin: 10px 0;
padding: 10px;
}
</style>
</head>
<body>
<p>Max 3 concurrent connection, wait for any response then continue next loop.</p>
<form id="upload-form" method="post">
<input type="hidden" name="hidden-name" value="hidden-value (unnecessary)">
<button type="submit">Submit</button>
<div id="debug"></div>
</form>
<script src="xhr.js"></script>
<script type="application/javascript">
let debugElement = document.getElementById('debug');
const thisForm = document.getElementById('upload-form');
const maxConcurrentConnection = 3;
thisForm.addEventListener('submit', (event) => {
event.preventDefault();
let loopPromise = Promise.resolve();
let ajaxCons = [];
for (let i = 0; i < 10; i++) {
loopPromise = loopPromise.then(() => {
if (ajaxCons.length < maxConcurrentConnection) {
debugElement.insertAdjacentHTML('beforeend', '<p>Calling to server round '+ i + '. (number from JavaScript.)</p>');
ajaxCons.push(
XHR('server.php?round=' + i)
.then((responseObject) => {
const response = responseObject.response;
console.log('response from server on js round ' + i);
debugElement.insertAdjacentHTML('beforeend', '<p> &nbsp; &gt; Response from server: Round: <code>' + response.round + '</code></p>');
return Promise.resolve(responseObject);
})
.catch((responseObject) => {
console.warn('response: ', responseObject);
debugElement.insertAdjacentHTML('beforeend', '<p style="color: red;"> &nbsp; &gt; Error! see console.</p>');
return Promise.reject(responseObject);
})
);
console.log('pushed ajaxCons round ' + i, ajaxCons);
if ((parseInt(ajaxCons.length)) === parseInt(maxConcurrentConnection)) {
console.log('Hold for server response at least one. ------------------');
return new Promise((resolve, reject) => {
Promise.any(
ajaxCons.map((promise, index) => {
//ajaxCons.splice(index, 1);
return promise;
})
)
.then((value) => {
console.log('value', value);
ajaxCons.splice(0, 1);
resolve();
});
});
}
}
});
}
});
</script>
</body>
</html>
<?php
// server.php
sleep(1);
$output = [];
$output['round'] = (int) ($_GET['round'] ?? 0);
header('Content-Type: application/json');
echo json_encode($output);
/**
* XHR function.
*
* You can change to use jQuery.ajax() or anything else.
*
* xhr.js
*/
function XHR(url, formData) {
return new Promise((resolve, reject) => {
let XHR = new XMLHttpRequest();
XHR.addEventListener('abort', (event) => {
reject({'response': '', 'status': (event.currentTarget ? event.currentTarget.status : ''), 'event': event});
});
XHR.addEventListener('error', (event) => {
reject({'response': '', 'status': (event.currentTarget ? event.currentTarget.status : ''), 'event': event});
});
XHR.addEventListener('timeout', (event) => {
reject({'response': '', 'status': (event.currentTarget ? event.currentTarget.status : ''), 'event': event});
});
XHR.addEventListener('load', (event) => {
let response = XHR.response;
let headers = XHR.getAllResponseHeaders();
let headerMap = {};
if (headers) {
let headersArray = headers.trim().split(/[\r\n]+/);
headersArray.forEach(function (line) {
let parts = line.split(': ');
let header = parts.shift();
let value = parts.join(': ');
headerMap[header] = value;
});
}
if (event.currentTarget && event.currentTarget.status >= 200 && event.currentTarget.status < 300) {
resolve({'response': response, 'status': event.currentTarget.status, 'event': event, 'headers': headerMap});
} else {
reject({'response': response, 'status': event.currentTarget.status, 'event': event, 'headers': headerMap});
}
});
XHR.open('POST', url);
XHR.responseType = 'json';
XHR.send(formData);
});// end new Promise
}// XHR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment