تغيير يؤدي إلى عطل: طُرق المزامنة لـ AccessHandles

يوفّر نظام الملفات الخاصة المصدر إمكانية الوصول إلى نوع خاص من الملفات تم تحسين أدائه بدرجة عالية، على سبيل المثال، من خلال توفير إذن وصول حصري ومباشر إلى محتوى الملف. ويمكن للمطوّرين الوصول إلى هذه الملفات من خلال استدعاء createSyncAccessHandle()، وهي طريقة تظهر على عناصر FileSystemFileHandle. ينتج عن هذه المكالمة FileSystemSyncAccessHandle.

FileSystemSyncAccessHandle هي عبارة عن ملف أولي يوفّر إمكانية وصول فعّال إلى الملفات المحلية. تتمثل إحدى حالات الاستخدام الرئيسية لهذه التطبيقات في التطبيقات التي تنقل رمز C/C++ إلى Wasm، إلا أنّ المكالمات غير المتزامنة ليست متوافقة بالكامل بعد مع Wasm، كما أنّ استخدام مكتبة Asyncify كبديل يؤدي إلى انخفاض كبير في الأداء. يؤدي جعل جميع طرق FileSystemSyncAccessHandle متزامنة إلى تطابُق التطبيق المتزامن مع واجهة برمجة تطبيقات Wasm والذي يشبه POSIX، ما يجعل واجهة برمجة التطبيقات أكثر سهولة في الاستخدام مع تحقيق مكاسب مهمة في الأداء.

الميزات الجديدة

يعرض FileSystemSyncAccessHandle الطُرق التالية التي كانت في السابق غير متزامنة، ولكنها متزامنة بدءًا من Chromium 108.

  • truncate(newSize): لتغيير حجم الملف المرتبط بمقبض الوصول إلى newSize بايت. إذا كان حجم الملف newSize أكبر من حجم الملف الحالي، سيؤدّي إلى إضافة بايت فارغ إلى الملف، وإلا يقتطع الملف.
  • getSize(): تعرض حجم الملف المرتبط بمؤشر الوصول بالبايت.
  • flush(): يتأكّد من أنّ محتوى الملف المرتبط بالاسم المعرِّف للوصول يتضمّن جميع التعديلات التي تم إجراؤها من خلال write().
  • close(): يتم مسح مقبض الوصول ثم إغلاقه. يؤدي إغلاق مؤشر الوصول إلى إيقاف أي عمليات أخرى فيه وتحرير القفل عند المَدخل المرتبط بمقبض الوصول.
// In a `Worker`:
const root = await navigator.storage.getDirectory();
const fileHandle = await root.getFileHandle('test', { create: true });
// `createSyncAccessHandle()` is still async.
const accessHandle = await fileHandle.createSyncAccessHandle();
// Both `read()` and `write()` were sync before.
accessHandle.read(/* ... */);
accessHandle.write(/* ... */);

// New: synchronous as of Chromium 108.
console.log(accessHandle.getSize());
accessHandle.truncate(123);
accessHandle.flush();
accessHandle.close();

ما هو الإجراء المطلوب اتّخاذه؟

تجدر الإشارة إلى أنّ تغيير الطرق من غير متزامنة إلى متزامنة هو تغيير عرضة على الويب مع تعطل محتمل. ومع أنّ استخدام await في طُرق متزامنة هو أمر لا، فإنّ أي استخدام لـ Promise.then() سيؤدي إلى إيقاف العملية. إذا أجريت سلسلة من استدعاء then() نتيجة لأي من الطرق غير المتزامنة السابقة والتي أصبحت الآن متزامنة، ستحتاج إلى تغيير رمزك.

// (✅) This won't break, but you better remove the superfluous `await`:
await accessHandle.flush();
// ✅ Correct:
accessHandle.flush();
// ⛔️ This will break, and you need to restructure your code:
accessHandle.flush().then(/* Follow-up code */);
// ✅ Correct:
accessHandle.flush();
/* Follow-up code */