ฉันใช้ ไลบรารี Q ของ kriskowal สำหรับโปรเจ็กต์ (เครื่องขูดเว็บ / โปรแกรมจำลองกิจกรรมของมนุษย์) และได้คุ้นเคยกับคำสัญญา โดยส่งคืนและ การแก้ไข/ปฏิเสธสิ่งเหล่านั้น และวิธีการควบคุมโฟลว์แบบอะซิงโครนัสพื้นฐานของไลบรารีและกลไกการโยน/จับข้อผิดพลาดได้รับการพิสูจน์แล้วว่าจำเป็น
ฉันพบปัญหาบางอย่างแล้ว การโทร promise.then
ของฉันและการโทรกลับของฉันมีแนวโน้มที่จะก่อตัวเป็นปิรามิด บางครั้งอาจเป็นเพราะเหตุผลในการกำหนดขอบเขต แต่บางครั้งก็เพื่อรับประกันลำดับเหตุการณ์ที่แน่นอน (ฉันคิดว่าฉันอาจแก้ไขปัญหาเหล่านี้ได้ด้วยการปรับโครงสร้างใหม่ แต่ต่อจากนี้ไปฉันต้องการหลีกเลี่ยง "นรกโทรกลับ" โดยสิ้นเชิง)
นอกจากนี้การดีบักยังน่าหงุดหงิดมาก ฉันใช้เวลามากมายในการ console.log
เพื่อค้นหาแหล่งที่มาของข้อผิดพลาดและจุดบกพร่อง หลังจากที่ฉันพบข้อผิดพลาดเหล่านั้นในที่สุด ฉันจะเริ่มโยนข้อผิดพลาดไปที่นั่นและจับข้อผิดพลาดเหล่านั้นที่อื่นด้วย promise.finally
แต่กระบวนการในการค้นหาข้อผิดพลาดในตอนแรกนั้นลำบาก
นอกจากนี้ ในโครงการของฉัน คำสั่งซื้อมีความสำคัญ ฉันต้องทำทุกอย่างตามลำดับ บ่อยครั้งที่ฉันพบว่าตัวเองสร้างอาร์เรย์ของฟังก์ชันที่ส่งคืนสัญญา จากนั้นเชื่อมโยงเข้าด้วยกันโดยใช้ Array.prototype.reduce
ซึ่งฉันไม่คิดว่าควรทำ
นี่คือตัวอย่างหนึ่งในวิธีการของฉันที่ใช้เทคนิคการลดขนาดนี้:
removeItem: function (itemId) {
var removeRegexp = new RegExp('\\/stock\\.php\\?remove=' + itemId);
return this.getPage('/stock.php')
.then(function (webpage) {
var
pageCount = 5,
promiseFunctions = [],
promiseSequence;
// Create an array of promise-yielding functions that can run sequentially.
_.times(pageCount, function (i) {
var promiseFunction = function () {
var
promise,
path;
if (i === 0) {
promise = Q(webpage);
} else {
path = '/stock.php?p=' + i;
promise = this.getPage(path);
}
return promise.then(function (webpage) {
var
removeMatch = webpage.match(removeRegexp),
removePath;
if (removeMatch !== null) {
removePath = removeitemMatch[0];
return this.getPage(removePath)
.delay(1000)
// Stop calling subsequent promises.
.thenResolve(true);
}
// Don't stop calling subsequent promises.
return false;
}.bind(this));
}.bind(this);
promiseFunctions.push(promiseFunction);
}, this);
// Resolve the promises sequentially but stop early if the item is found.
promiseSequence = promiseFunctions.reduce(function (soFar, promiseFunction, index) {
return soFar.then(function (stop) {
if (stop) {
return true;
} else {
return Q.delay(1000).then(promiseFunction);
}
});
}, Q());
return promiseSequence;
}.bind(this))
.fail(function (onRejected) {
console.log(onRejected);
});
},
ฉันมีวิธีอื่นที่ทำสิ่งเดียวกันโดยพื้นฐานแล้ว แต่ต้องทนทุกข์ทรมานจากปัญหาการเยื้องที่แย่กว่ามาก
ฉันกำลังพิจารณาปรับโครงสร้างโครงการใหม่โดยใช้ไลบรารี async ของ coalan ดูเหมือนคล้ายกับ Q แต่ฉันอยากรู้ว่ามันแตกต่างกันอย่างไร ความประทับใจที่ฉันได้รับคือ async "callback-centric" มากกว่าในขณะที่ Q คือ "promise-centric"
คำถาม: เมื่อพิจารณาถึงปัญหาและข้อกำหนดของโครงการ ฉันจะได้รับและ/หรือสูญเสียอะไรจากการใช้ async บน Q ห้องสมุดเปรียบเทียบกันอย่างไร? (โดยเฉพาะอย่างยิ่งในแง่ของการดำเนินการชุดของงานตามลำดับและการดีบัก/การจัดการข้อผิดพลาด)
.series
และ.eachSeries
แน่นอนว่า .then chain สามารถบรรลุเป้าหมายเดียวกันได้ - person Kevin B   schedule 04.08.2014