افترض أن لدي بنية دليل مشابهة لما يلي:
foo
|
+---one
| +---tmp
|
+---two
|
+---three
|
+---tmp
أريد الحصول على قائمة الدلائل الفرعية تحت foo
الذي لديه tmp
(sub) دليل فرعي تحته. لدي الكود التالي الذي يفعل ذلك:
const { bindNodeCallback, from } = require('rxjs');
const { map, flatMap, filter } = require('rxjs/operators');
const { readdir, access, accessSync, constants: { F_OK, R_OK }} = require('fs');
const { join } = require('path');
const readdirRx = bindNodeCallback(readdir);
const FOO = './foo';
const result = readdirRx(FOO)
.pipe(
// readdir will return an array of files. Convert each
// file into an observable, and then flatten it.
flatMap(from),
// get rid of directories that do not have a `tmp` dir underneath
filter(dir => {
try {
accessSync(join(FOO, dir, 'tmp'), F_OK | R_OK);
return true;
} catch (err) {
return false;
}
})
);
result.subscribe(console.log, console.error, () => console.log('Done!'));
// outputs (correctly):
// one
// three
// Done!
ومع ذلك ، يبدو هذا الرمز فظيعًا بالنسبة لي لأنه (أ) أستخدم استثناءات لتدفق التحكم ، و (ب) هناك تزامن accessSync
استدعاء ، وكلاهما يضر بالأداء.
لديّ الرمز التفاعلي التالي الذي يتحقق من نفس الشيء:
const fileExistsAndReadableRx = bindNodeCallback(
// check if file exists and readable
(file, cb) => access(file, F_OK | R_OK,
// call the callback with true if no errors found
err => cb(!err)
)
);
ومع ذلك ، لا يمكنني معرفة كيف يمكنني التوصيل fileExistsAndReadableRx
في البرنامج أعلاه. هدفي هو إزالة كتلة المحاولة واستخدام fileExistsAndReadableRx
بدلا من ذلك لتصفية الدلائل الفرعية التي ليس لديها tmp
(sub) دليل فرعي. كيف أقوم بذلك؟
(يرجى ملاحظة أن المهمة الفعلية التي أحاول القيام بها هي عدم قراءة القرص. ما أحاول القيام به هو عملية معقدة غير متزامنة ، وكان عليّ أن أتوصل إلى مثال أبسط لتوضيح مشكلتي).
ما حاولت حتى الآن:
حاولت استخدام map
، ولكنها تنبعث منها تيار من المرصدات ، كما يتوقع المرء:
const result = readdirRx(FOO)
.pipe(
flatMap(from),
map(dir =>
fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
)
);
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
// Observable { _isScalar: false, _subscribe: [Function] }
// Observable { _isScalar: false, _subscribe: [Function] }
// Observable { _isScalar: false, _subscribe: [Function] }
// Done!
لذا فكرت ، أعرف! سأستخدم flatMap
لتسطي المرصد. يجب أن ينتج عن ذلك ثلاث قيم منطقية تنبعث في النهاية من تلك المرصدات . لكن ذلك لم ينجح أيضا. تنبعث فقط قيمة واحدة:
const result = readdirRx(FOO)
.pipe(
flatMap(from),
flatMap(dir =>
fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
)
);
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
// true
// Done!
تعديل:
حاولت IngoBurk الصورة الجواب ، ولكن أن تنتج قيمة منطقية واحدة. لا قائمة سلاسل كما أتوقع:
const result = readdirRx(FOO)
.pipe(
flatMap(from),
flatMap(dir => fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
.pipe(
filter(Boolean),
map(() => dir),
)
),
);
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
// true
// Done!