Register Register Member Login Member Login Member Login Forgot Password ??
PHP , ASP , ASP.NET, VB.NET, C#, Java , jQuery , Android , iOS , Windows Phone
 

Registered : 109,027

HOME > Client Script Forum > ตัวอย่างการเรียก Ajax (XHR) แบบหลายการเชื่อมต่อพร้อมกันแบบมีขีดจำกัด



 

ตัวอย่างการเรียก Ajax (XHR) แบบหลายการเชื่อมต่อพร้อมกันแบบมีขีดจำกัด

 



Topic : 136201



โพสกระทู้ ( 4,719 )
บทความ ( 8 )



สถานะออฟไลน์




ในการเรียกใช้ Ajax หรือ XHR นั้นบางครั้งจำเป็นจะต้องเรียกหลาย URL ต่อครั้ง ยกตัวอย่างเช่นการอัพโหลดแบบ chunk เป็นต้น. การเรียก 1 ครั้ง ปกติแล้ว JavaScript จะไม่รอให้ว่าจะสำเร็จก่อนแล้วค่อยไปต่อหรืออย่างไร แต่มีเท่าไหร่มันก็สั่งเรียกให้หมดเลย ทำให้บางครั้งเกิดการเรียก URL เต็มจนท่วม server ส่งผลให้ firewall มองว่าเป็นการโจมตีแล้วทำการบล็อคไปเลย เช่นนี้เป็นต้น.

การจำกัดจำนวนการเรียกใช้ Ajax หลายๆรายการต่อครั้งจึงเป็นสิ่งจำเป็น. ต่อไปนี้เป็นโค้ดตัวอย่าง

Code (JavaScript)
/**
 * Function สำหรับเรียก XHR อย่างง่ายๆ จะเปลี่ยนไปใช้ jQuery.ajax() ก็ได้เช่นกัน.
 */
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

xhr.js




Code (PHP)
<?php
// server.php

sleep(1);

$output = [];

$output['round'] = (int) ($_GET['round'] ?? 0);

header('Content-Type: application/json');

echo json_encode($output);

server.php




Code
<!--demo.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>

demo.html




จากโค้ดตัวอย่างด้านบน มันจะทำการจำลองเรียก URL หลายๆครั้งผ่าน for loop. ทุกๆครั้งที่เรียก จะผลักการเรียกเข้าไปใน array ajaxCons โดยเช็คไม่ให้เกิดจำนวน concurrent หรือการเชื่อมต่อพร้อมกันสูงสุดที่กำหนดไว้คือ 3. ถ้าหากเกินจำนวน ก็จะทำการรอผ่าน Promise object.

เมื่อทุกๆ request ทำงานเสร็จแล้วด้วยการตรวจผ่าน Promise.all() มันจะทำการ resolve เพื่อคลายการรอให้ loop รอบต่อไปทำงานได้อีก 3 การเชื่อมต่อ โดยจะทำซ้ำแบบนี้ไปเรื่อยๆจนกว่าจะครบ 10 รอบ.

ทั้งนี้หากผู้อ่านจะดัดแปลงให้เสร็จเฉพาะ request ใดๆไม่ต้องรอทั้งหมดก็ได้เช่นกัน โดยแก้ไขบรรทัดที่เป็นโค้ด ajaxCons = []; มาเป็นajaxCons.splice(0, 1); และเปลี่ยนจาก Promise.all() มาเป็น Promise.any().

ดูตัวอย่างซอร์สโค้ดเต็มบน GitHub.

Original: https://rundiz.com/?p=728



Tag : JavaScript, Ajax









ประวัติการแก้ไข
2021-06-17 21:12:32
Move To Hilight (Stock) 
Send To Friend.Bookmark.
Date : 2021-06-17 18:51:31 By : mr.v View : 586 Reply : 0
 

   

ค้นหาข้อมูล


   
 

แสดงความคิดเห็น
Re : ตัวอย่างการเรียก Ajax (XHR) แบบหลายการเชื่อมต่อพร้อมกันแบบมีขีดจำกัด
 
 
รายละเอียด
 
ตัวหนา ตัวเอียง ตัวขีดเส้นใต้ ตัวมีขีดกลาง| ตัวเรืองแสง ตัวมีเงา ตัวอักษรวิ่ง| จัดย่อหน้าอิสระ จัดย่อหน้าชิดซ้าย จัดย่อหน้ากึ่งกลาง จัดย่อหน้าชิดขวา| เส้นขวาง| ขนาดตัวอักษร แบบตัวอักษร
ใส่แฟลช ใส่รูป ใส่ไฮเปอร์ลิ้งค์ ใส่อีเมล์ ใส่ลิ้งค์ FTP| ใส่แถวของตาราง ใส่คอลัมน์ตาราง| ตัวยก ตัวห้อย ตัวพิมพ์ดีด| ใส่โค้ด ใส่การอ้างถึงคำพูด| ใส่ลีสต์
smiley for :lol: smiley for :ken: smiley for :D smiley for :) smiley for ;) smiley for :eek: smiley for :geek: smiley for :roll: smiley for :erm: smiley for :cool: smiley for :blank: smiley for :idea: smiley for :ehh: smiley for :aargh: smiley for :evil:
Insert PHP Code
Insert ASP Code
Insert VB.NET Code Insert C#.NET Code Insert JavaScript Code Insert C#.NET Code
Insert Java Code
Insert Android Code
Insert Objective-C Code
Insert XML Code
Insert SQL Code
Insert Code
เพื่อความเรียบร้อยของข้อความ ควรจัดรูปแบบให้พอดีกับขนาดของหน้าจอ เพื่อง่ายต่อการอ่านและสบายตา และตรวจสอบภาษาไทยให้ถูกต้อง

อัพโหลดแทรกรูปภาพ

Notice

เพื่อความปลอดภัยของเว็บบอร์ด ไม่อนุญาติให้แทรก แท็ก [img]....[/img] โดยการอัพโหลดไฟล์รูปจากที่อื่น เช่นเว็บไซต์ ฟรีอัพโหลดต่าง ๆ
อัพโหลดแทรกรูปภาพ ให้ใช้บริการอัพโหลดไฟล์ของไทยครีเอท และตัดรูปภาพให้พอดีกับสกรีน เพื่อความโหลดเร็วและไฟล์ไม่ถูกลบทิ้ง

   
  เพื่อความปลอดภัยและการตรวจสอบ กระทู้ที่แทรกไฟล์อัพโหลดไฟล์จากที่อื่น อาจจะถูกลบทิ้ง
 
โดย
อีเมล์
บวกค่าให้ถูก
<= ตัวเลขฮินดูอารบิก เช่น 123 (หรือล็อกอินเข้าระบบสมาชิกเพื่อไม่ต้องกรอก)







Exchange: นำเข้าสินค้าจากจีน, Taobao, เฟอร์นิเจอร์, ของพรีเมี่ยม, ร่ม, ปากกา, power bank, แฟลชไดร์ฟ, กระบอกน้ำ

Load balance : Server 04
ThaiCreate.Com Logo
© www.ThaiCreate.Com. 2003-2024 All Rights Reserved.
ไทยครีเอทบริการ จัดทำดูแลแก้ไข Web Application ทุกรูปแบบ (PHP, .Net Application, VB.Net, C#)
[Conditions Privacy Statement] ติดต่อโฆษณา 081-987-6107 อัตราราคา คลิกที่นี่