أواجه مشكلة في استخدام غير متزامن في أحد اختبارات التكامل التي تتضمن معالجات الأحداث. تكمن المشكلة في أن معالج الحدث يحتاج إلى الإعداد (مع الإشارة إلى رد نداء غير متزامن متوفر) قبل إرسال الحدث. ومع ذلك ، يحتاج رمز معالج الحدث إلى رد اتصال إضافي على الفور.
فيما يلي مثال مبسط يوضح المشكلة:
async.auto({
// This needs to run first, but it will finish second
event: [(next) => {
emitter.once('awesome', next);
}],
// This needs to finish near the end
checkResults: ['event', (results, next) => {
assert(results.event.status == 200);
assert(results.event.msg == 'cool');
// Do other async stuff...
somethingAsync(next);
}],
// This has to start second, but before the first one finishes
emit: ['event', (results, next) => {
event.emit('awesome', {msg: 'cool'}, next);
}],
checkEmit: ['emit', (results, next) => {
// some sort of check that can be async
},
], done);
يجب أن يبدأ event
أولاً ، لكنه لن ينتهي حتى يظهر emit
. يحتاج emit
إلى الانتظار حتى يبدأ event
، ولكن لا ينتهي (يُعرف أيضًا باسم إعداد المعالج). وبالتالي هذا لن ينتهي.
هل هناك طريقة للقيام بذلك مع مكتبة غير متزامنة الحالية؟ (بطريقة نظيفة)
هذا هو الحل الذي أرغب فيه ، بافتراض أنه يمكن تنفيذه بطريقة غير متزامنة
async.auto({
listen: [(next, done) => {
client.on(done);
return next();
},
...
}, callback);
يمكنني استخدام التوازي ، تشغيل أجهزة الإرسال والمستمعين (التي يمكن أن يكون هناك العديد منها في الاختبار) كمجموعة من المهام. أخذ النتائج وتشغيل الشيكات كجزء ثانٍ. ومع ذلك ، لا يلزم التوازي من الناحية الفنية لبدء المهام بالترتيب (على الرغم من أنه من المحتمل أن يحدث ذلك). أيضًا ، يصبح الرمز أقل ثباتًا ، خاصة في الإعدادات الأكثر تعقيدًا.
مرحبا Saevon ، شكرا على السؤال!
هناك طريقة سريعة ونظيفة للقيام بذلك وهي:
async.auto({
// This needs to finish near the end
checkResults: [(next) => {
return next(null, (results, next) => {
assert(results.event.status == 200);
assert(results.event.msg == 'cool');
// Do other async stuff...
// somethingAsync(next);
});
}],
// This needs to run first, but it will finish second
event: ['checkResults', (handler, next) => {
emitter.once('awesome', handler.checkResults);
return next();
}],
// This has to start second, but before the first one finishes
emit: ['event', (results, next) => {
// Should this be emitter.emit instead of event.emit?
event.emit('awesome', {msg: 'cool'}, next);
}],
checkEmit: ['emit', (results, next) => {
// the results of `checkResults` will be in `results.emit`
// as the handler on 'awesome' was passed the `next`
// callback from `emit`
// some sort of check that can be async
yourChecks(next);
}]
}, function done(err) {
// everything finished running, unless `err` !== `null`
});
بشكل أساسي ، تقوم فقط بتبديل التبعية event
و checkResults
، والتي قد تكون في الواقع أكثر نظافة ، حيث يعتمد event
على المعالج في checkResults
. checkResults
بتمرير المعالج إلى event
.
سيكون أمر التنفيذ:
checkResults --> event --> emit --> handler (passed to event from checkResults) --> checkEmit --> done
.
اسمحوا لي أن أعرف إذا كان أي شيء غير واضح.
نعم ، هذا يحل المشكلة. شكرا!
أعتقد أن هذه هي أكثر حالات استخدام السيارات جنونًا التي رأيتها بالمناسبة: building_construction:
متفق. عادةً لا تختلط عمليات الاسترجاعات غير المتزامنة وبواعث الأحداث جيدًا ...
التعليق الأكثر فائدة
أعتقد أن هذه هي أكثر حالات استخدام السيارات جنونًا التي رأيتها بالمناسبة: building_construction: