Synchronous AJAX calls

วันก่อนผมเจอปัญหาอย่างหนึ่ง ในการสร้าง request ด้วย AJAX เป็นที่รู้กันดีว่า request ที่ออกไปจะมีการทำงานแบบ Asynchronous และด้วยความสามารถของ HTML+JavaScript ทำให้เราสามารถตอบสนอง response ที่กลับมาได้โดยสะดวกมากขึ้นโดยที่ไม่ต้องรอ response ที่ยังไม่กลับมา

ปัญหาที่ผมเจอคือ ในการยิง request ครั้งละมากๆ เช่น 500 request และในแต่ละ request มี overhead และ process/server time ที่สูงมากๆ การทำงานของ script นั้นมันจะผิดพลาด ผลลัพธ์ที่เจอคือ มีแค่ request สุดท้ายเท่านั้นที่ reponse กลับมา ซึ่งอาจจะเป็นปัญหาจากตัว host ที่ผมเช่าอยู่ก็ได้ ซึ่งเป็นแบบ share host นั้นไม่ยอมให้มี request ไปที่ไซต์อื่นๆ, ในกรณีของผมเป็นลักษณะ Cross-site แต่เป็น การทำ Cross-site ที่ฝั่ง server, browser รุ่นใหม่จะมีการป้องกันหรือแจ้งเตือน ในกรณีที่มีการทำ Cross-site ที่ฝั่ง client เหตุผลเรื่อง security

กลับมาที่ปัญหาของ host ของผม เท่าที่วิเคราะห์เองน่าจะเกิดจาก

1. server ไม่ยอมให้มี request ไปที่ site ที่มีลักษณะเป็น Cross-site มากกว่าหนึ่ง site ณ.เวลาเดียวกัน

2. server ไม่ยอมให้มีการทำ Cross-site

และเนื่องจาก application ที่ผมเขียนขึ้นมา มีการจัดการ response แบบ Asynchronous คือจัดการ response แบบไม่เรียงลำดับ อธิบายเพิ่มเติมแล้วกันว่า application ของผมมีการยิง request ไปในหลายๆ site เพื่อดึงข้อมูลอะไรบางอย่างจาก site เหล่านั้น ซึ่งข้อมูลที่ได้กลับมาก็จะถูกจัดการแบบ Asynchronous และแสดงผลที่หน้าจอ แต่ผมไม่สามารถใช้การทำงานแบบ Asynchronous Ajax calls ได้

สิ่งที่ผมต้องทำคือ สร้าง request แบบ Synchronous Ajax calls โดยยิง request ไปครั้งละหนึ่ง site และจัดการ response data ตรงนั้นให้เสร็จทีละอันไป code จากการค้นคว้าใน internet และจับ code เหล่านั้นมายำๆรวมกัน มั่วๆบ้าง ลองผิดลองถูก สุดท้ายก็ได้ code นี้ออกมาครับ

[source language=”JavaScript”]
var isProgress = false;

// Synchronous Ajax calls handler function
function syncAjaxHandler() {
isProgress = false;
makeAjaxCall();
}

function makeAjaxCall(){
if (!isProgress) {
isProgress=true;

// send a request
makeRequest();

// call itself
makeAjaxCall();
} else {
// if current request is work in progess, wait 500ms.
setTimeout("makeAjaxCall()", 500);
}
}

function makeRequest() {
var xmlHttp;

if (window.XMLHttpRequest) {
// code for IE7+, FF, Chrome, Opera, Safari
xmlHttp=new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}

xmlHttp.onreadystatechange=function() {
if (xmlHttp.readyState==4 && xmlHttp.status==200) {

// do someting with response text
var response = xmlHttp.responseText;
// job done
isProgress=false;
}
}

xmlHttp.open("GET", "somewhere");
xmlHttp.send();
}
[/source]

บรรดทัดที่สำคัญคร่าวๆมีดังนี้

[source language=”JavaScript”]
isProgress = false;
[/source]

ในบรรทัดที่ 1 isProgress ที่จะบอกว่าในขณะนั้นมี work ของ request ปัจจุบัน in progress อยู่หรือป่าว ถ้ายังมีอยู่ก็จะยังไม่มีการยิง request ถัดไป จนกว่า request นั้นจะ response กลับมา

[source language=”JavaScript”]
setTimeout("syncAjaxCall()", 500);
[/source]

ในบรรทัดที่ 20 ถ้ายังมี progress อยู่ก็จะยังไม่สร้าง request ใหม่ขึ้นมา ให้รอไปอีก 500ms

[source language=”JavaScript”]
isProgress=false;
[/source]

ในบรรทัดที่ 41 เมื่อ job done เซ็ต isProgress เป็น false เพื่อบอกว่าสามารถสร้าง request ใหม่ได้แล้ว

นั้นคือโค้ดที่ทำ Ajax calls ให้มีการทำงานแบบ Synchronous ทั้งๆที่ข้อด๊และคุณสมบัติของ Ajax คือ Asynchronous งงมั้ย?? และบล็อกนี้เป็นบล็อกที่ผมเขียนขึ้นเอง อาจจะผิดจะถูกบ้างในคอนเซ็ปหรือคำศัพท์ต่างๆ เพราะตอนที่เขียนมันขึ้นมาผมก็มั่วเอา เลยอยากเขียนเก็บไว้กันลืม และเผื่อจะเป็นประโยชน์บ้างไม่มากก็น้อยกับใครสักคน

ภาพจาก adaptivepath.com

Leave a Reply

Your email address will not be published.