ทางเลือกที่สะอาดกว่าสำหรับสิ่งที่ @Ivo แนะนำคือAsynchronous Method Queueโดยสมมติว่าคุณต้องทำการเรียก async เพียงครั้งเดียวสำหรับคอลเลกชัน
(ดูโพสต์นี้โดย Dustin Diaz สำหรับคำอธิบายโดยละเอียดเพิ่มเติม)
function Queue() {
this._methods = [];
this._response = null;
this._flushed = false;
}
(function(Q){
Q.add = function (fn) {
if (this._flushed) fn(this._response);
else this._methods.push(fn);
}
Q.flush = function (response) {
if (this._flushed) return;
this._response = response;
while (this._methods[0]) {
this._methods.shift()(response);
}
this._flushed = true;
}
})(Queue.prototype);
คุณเพียงแค่สร้างอินสแตนซ์ใหม่Queueเพิ่มการเรียกกลับที่คุณต้องการจากนั้นล้างคิวด้วยการตอบสนองแบบ async
var queue = new Queue();
queue.add(function(results){
for (var result in results) {
}
});
someFunction(param1, param2, function(results) {
queue.flush(results);
}
ประโยชน์เพิ่มเติมของรูปแบบนี้คือคุณสามารถเพิ่มฟังก์ชันต่างๆลงในคิวแทนที่จะเป็นเพียงฟังก์ชันเดียว
หากคุณมีออบเจ็กต์ที่มีฟังก์ชันตัววนซ้ำคุณสามารถเพิ่มการรองรับสำหรับคิวนี้เบื้องหลังและเขียนโค้ดที่ดูเหมือนซิงโครนัส แต่ไม่ใช่:
MyClass.each(function(result){ ... })
เพียงแค่เขียนeachเพื่อใส่ฟังก์ชันที่ไม่ระบุชื่อลงในคิวแทนที่จะดำเนินการทันทีจากนั้นจึงล้างคิวเมื่อการเรียก async ของคุณเสร็จสมบูรณ์ นี่เป็นรูปแบบการออกแบบที่เรียบง่ายและทรงพลัง
PS หากคุณกำลังใช้ jQuery คุณมีวิธีการคิว async ที่จำหน่ายของคุณเรียกว่าjQuery.Deferred
( /* ... */ )ดูเหมือนสัตว์ประหลาดและตอนนี้ฉันกลัว :(