Async وAwait
جزء من قسم أساسيات Node.js في رحلة Node.js على Coddy. الدرس 23 من 33.
تُقرأ سلسلة من استدعاءات .then على نحو مختلف عن الطريقة التي تفكر بها في الخطوات: اقرأ، ثم حلّل، ثم احفظ.
داخل دالة async، يتوقف await مؤقتًا حتى يستقر الوعد، ويعطيك قيمته. إذا أخفق الوعد، فسيُطلق خطأ عندها، لذا يتولى try وcatch التعامل معه. وفي الوحدة، يعمل await أيضًا على المستوى الأعلى.
import { readFile } from 'node:fs/promises';
const loadConfig = async () => {
try {
return JSON.parse(await readFile('config.json', 'utf8'));
} catch {
return {};
}
};
const config = await loadConfig();
console.log(config.port ?? 3000);تعيد دالة async وعدًا دائمًا، لذا ينتظرها المستدعي باستخدام await أيضًا. إذا نسيت await، فستحصل على الوعد نفسه، Promise { <pending> }، بدلًا من قيمته.
التحدي
سهلتفتح هذه الخطوة مشروع أداة سطر الأوامر للملاحظات المُعدّة في الدورة، وليس ملفات مشروعك من درس Promises (بما فيها count.js). يبقى عملك السابق في درسه الخاص. اقرأ الملفات المرفقة قبل تعديل store.js. تحتوي هذه النسخة على قارئ الملاحظات المعتمد على الوعود ومعالجة الأخطاء الخاصة به.
يستخدم store.js الآن نسختَي الوعود من readFile وwriteFile، وأصبحت طرائقه async. لكن لا شيء ينتظر اكتمال الوعود حتى الآن، لذا تتعطل كل الأوامر. أضف await في كل موضع يجب أن يكتمل فيه وعد قبل الخطوة التالية.
- في
store.js، داخلload، انتظر اكتمالreadFileقبل أن يستخدمJSON.parseالنص. - في
store.js، الدالةloadهيasync، لذا فهي تُرجع وعدًا. انتظره في الموضع الذي يعيّن فيه المخزن قيمةnotes. يمكن للوحدة استخدامawaitفي المستوى الأعلى، خارج أي دالة. - في
store.js، انتظر اكتمالwriteFileفيsave، وانتظر اكتمالthis.save()فيaddوremove. - في
notes.js، أصبحتstore.addوstore.removeالآنasync. انتظرهما في فرعيaddوdone، كي يحتويnوremovedعلى قيم لا وعود.
وهكذا يصبح لديك سبعة مواضع لاستخدام await إجمالًا. عندئذٍ يعمل كل أمر كما كان من قبل. يعرض list الملاحظات الموجودة في notes.json. مع ملاحظتَي البداية، يطبع add Buy bread العبارة Saved note 3.، ثم يطبع done 1 العبارة Done: Buy milk.
جرّب ذلك: اكتب list في المربع بعد $ node notes.js قبل أن تغيّر أي شيء. سترى notes.json is damaged: ...، لكن الملف سليم: فقد أُعطي JSON.parse وعدًا بدلًا من نص الملف. بعد إجراء تغييراتك، يعرض list الملاحظات مجددًا. ثم اكتب add Buy bread وسترى Saved note 3.. اكتب done 1 وسترى Done: Buy milk.
جرّب بنفسك
import { existsSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';
const file = 'notes.json';
// تُرجع readFile وwriteFile الآن وعودًا. انتظر كلًّا منهما باستخدام await.
const load = async () => {
if (!existsSync(file)) {
return [];
}
try {
return JSON.parse(readFile(file, 'utf8'));
} catch (err) {
console.error(`notes.json is damaged: ${err.message}`);
process.exit(1);
}
};
const store = {
notes: load(),
async save() {
writeFile(file, JSON.stringify(this.notes, null, 2));
},
async add(text) {
this.notes.push(text);
this.save();
return this.notes.length;
},
async remove(n) {
const [text] = this.notes.splice(n - 1, 1);
this.save();
return text;
},
};
export default store;
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس أساسيات Node.js
1تشغيل JavaScript على Node
مرحبًا يا Nodeقراءة الأمروسائط سطر الأوامرالأوامر4البرمجة غير المتزامنة في Node
استخدام نتيجة دالة الاستدعاءدوال الاستدعاءنتيجة Promiseعندما يفشل Promiseالوعودانتظار قيمةAsync وAwaitقراءتان مستقلتانPromise.allحلقة الأحداثالمؤقتاتتدرّب بنفسك: Playground لـ Express