Aborting Previous Xmlhttprequest
Solution 1:
If you're going to abort the request anyway, you might as well instead prevent the request from being sent in the first place if you detect that the user is still typing.
var timeout, timer = 150;
functionsearchfunc(value) {
clearTimeout(timeout);
setTimeout(function () {
if (value!='') {
var xmlhttp = CreateXmlHttp();
xmlhttp.open('GET','http://example.com/ajax/instant_search.php?q='+value,true);
xmlhttp.send(null);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById('search_result').innerHTML = xmlhttp.responseText+'<li><a href="http://example.com/search.php?q='+value+'">full search for <strong>'+value+'</strong></a></li>';
}
}
} elsedocument.getElementById('search_result').innerHTML = '';
}, timer);
}
What this will do is when the user presses a key, a setTimeout is started that waits 150ms. If the function is triggered again within 150ms, the interval is cleared and restarted. Once the interval finally finishes, the ajax request is made.
This is identical to using an abort other than the fact that the server isn't bombarded with ajax requests that you would have aborted anyway, and a 150ms latency is added to the request.
There are libraries out there that will handle this even better such as http://benalman.com/projects/jquery-throttle-debounce-plugin/ (it doesn't require jQuery)
Using the plugin you could have it instead send no more than 1 request per timer ms, resulting in the first key always sending a request, and another not being sent until timer ms has passed, giving you a more real-time looking result.
Solution 2:
Here I am sharing some overview of what I did in my stencilsjs project to achieve this scenario,
firstly I have created the separate xmlApi.ts common file for my project and wrote following code in that
// common XMLHttpRequest for handling fetch request // currently using this XMLHttpRequest in search component to fetch the datalet xmlApi
// Create the XHR requestconst request = newXMLHttpRequest()
constfetchRequest = (url: string, params: any) => {
// Return it as a PromisereturnnewPromise((resolve, reject) => {
// Setup our listener to process compeleted requests
request.onreadystatechange = () => {
// Only run if the request is completeif (request.readyState !== 4) { return }
// Process the responseif (request.status >= 200 && request.status < 300) {
// If successfulresolve(request)
} else {
// If failedreject({
status: request.status,
statusText: request.statusText
})
}
}
// If error
request.onerror = () => {
reject({
status: request.status,
statusText: request.statusText
})
}
// Setup our HTTP request
request.open(params.method, url, true)
// Setup our HTTP request headersif (params.headers) {
Object.keys(params.headers).forEach(key => {
request.setRequestHeader(key, params.headers[key])
})
}
// Send the request
request.send(params.body)
})
}
xmlApi = {
// exporting XMLHttpRequest object to use in search component to abort the previous fetch calls
request,
fetchRequest
}
exportdefault xmlApi
Second I have passed the event object with onTextInput method to get the input value using event.target.value
HTMl:
<input id="search_box" type="text" placeholder="type to search..."
onInput={event => { this.onTextInput(event) }}/>
Sample HTML for suggestion :
Here based on the showSuggestionListFlag ,i have shown the search suggestionlist, also used css to align div and input tag properly
<div class={'search-result ' + (this.showSuggestionListFlag ? 'show' : '')}>
<ul class="dropdown-list">
{this.responseData && this.responseData.map((item, index) => (
<li class="list-element">{item} </li>
))}
</ul>
</div>
Third in my ts code, i imported the my xmlApi
Here i have just written some logic code from my code, I have also used async and await to handle promise/reject in my project code, according to your code you can handle your own promise/reject
code:
import xmlApi from'./xmlApi'
onTextInput (event) { // first created bodydata here using `event.target.value`const opts = {
method: 'POST',
body: bodyData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
}
try {
// aborting the previous xhr request callif (xmlApi.request) {
xmlApi.request.abort()
}
const responseData = xmlApi.fetchRequest(endPointUrl, opts)
.then(data => {
consolep.log(`xhr request success`)
returnJSON.parse(data['response'])
})
.catch(error => {
console.log.debug(`xhr request cancelled/failed : ${JSON.stringify(error)}`)
}) //use responseDataif(responseData){this.showSuggestionListFlag = true}
} catch (e) {
console.log(`fetch failed`, e)
}
}
This is my first answer on Stack Overflow. Thanks!!
Post a Comment for "Aborting Previous Xmlhttprequest"