
يوم جيد يا اصدقاء!
أقدم إليكم ترجمة مقال آبل شاه ،
"أخطاء الجافا سكريبت الوعد التي يجب على كل مبتدئ أن يعرفها ويتجنبها
" .
جافا سكريبت وعود مهمة يجب على الجميع معرفتها
أرغب في معرفة هذه الأخطاء عندما درست JavaScript والوعود.
عندما يتصل بي أحد مطوري البرامج ويشتكي من أن رمزه لا يعمل أو يتم تنفيذه ببطء ، فأولًا وقبل كل شيء اهتم بهذه الأخطاء. عندما بدأت البرمجة قبل 4 سنوات ، لم أكن أعرف عنها وكنت معتادًا على تجاهلها. ومع ذلك ، بعد تعييني لمشروع يعالج حوالي مليون طلب في غضون دقائق قليلة ، لم يكن لدي أي خيار سوى تحسين الكود الخاص بي (حيث وصلنا إلى مستوى أصبح فيه التوسع الرأسي مستحيلًا).
لذلك ، أود في هذه المقالة أن أتحدث عن الأخطاء الأكثر شيوعًا عند العمل مع الوعود في JS ، والتي لا ينتبه الكثيرون إليها.
خطأ # 1. باستخدام كتلة try / catch داخل الوعد
يعد استخدام كتلة try / catch داخل الوعد أمرًا غير عملي ، لأنه إذا ألقى رمزك خطأ (داخل الوعد) ، فسيتم اعتراضه بواسطة معالج الأخطاء في الوعد نفسه.
هذا هو ما يدور حوله هذا:
new Promise((resolve, reject) => { try { const data = someFunction()
بدلاً من ذلك ، اسمح للشفرة بمعالجة الخطأ خارج الوعد:
new Promise((resolve, reject) => { const data = someFunction()
سيعمل هذا دائمًا ، باستثناء ما هو موضح أدناه.
الخطأ رقم 2. استخدام وظيفة غير متزامن داخل وعد
عند استخدام الوظيفة غير المتزامنة ، تحدث بعض الآثار الجانبية غير السارة ضمن الوعد.
لنفترض أنك قررت إجراء بعض المهام غير المتزامنة ، وأضف الكلمة الأساسية "غير متزامن" إلى الوعد ، ورمت الكود خطأً. ومع ذلك ، الآن لا يمكنك معالجة هذا الخطأ إما .catch () أو تنتظر:
في كل مرة أقابل فيها وظيفة غير متزامنة داخل وعد ، أحاول فصلها. وأحصل عليه في 9 من أصل 10 حالات. ومع ذلك ، هذا ليس ممكنًا دائمًا. في هذه الحالة ، ليس لديك خيار سوى استخدام كتلة try / catch داخل الوعد (نعم ، هذا يناقض الخطأ الأول ، ولكن هذا هو السبيل الوحيد للخروج):
new Promise(async(resolve, reject) => { try { throw new Error('message') } catch(error) { reject(error) } }).catch(e => console.log(e.message))
خطأ رقم 3. نسيان .catch ()
هذا أحد تلك الأخطاء التي لا تشك في وجودها حتى يبدأ الاختبار. أو ، إذا كنت ملحدًا لا يؤمن بالاختبارات ، فسوف يتعطل
إنتاج الشفرة بالتأكيد. لأن الإنتاج يتبع بصرامة
قانون مورفي ، الذي ينص على: "أي شيء يمكن أن يحدث خطأ سيحدث خطأ" (يمكنك ترجمة هذا: "إذا حدث خطأ ما ، فسيحدث ذلك" ؛ التشبيه باللغة الروسية هو "قانون المعنى" - تقريبا.
لجعل الرمز أكثر أناقة ، يمكنك التفاف الوعد في try / catch بدلاً من استخدام .then (). Catch ().
الخطأ رقم 4. لا تستخدم Promise.all ()
Promise.all () هو صديقك.
إذا كنت مطور محترف ، فربما تفهم ما أريد أن أقوله. إذا كان لديك العديد من الوعود التي لا تعتمد على بعضها البعض ، يمكنك تنفيذها في نفس الوقت. افتراضيًا ، يتم تنفيذ الوعود بالتوازي ، ولكن إذا كنت بحاجة إلى تنفيذها بالتتابع (باستخدام الانتظار) ، فسوف يستغرق الأمر الكثير من الوقت. Promise.all () يمكن أن تقلل إلى حد كبير الكمون:
const {promisify} = require('util') const sleep = promisify(setTimeout) async function f1() { await sleep(1000) } async function f2() { await sleep(2000) } async function f3() { await sleep(3000) }
الآن مع Promise.all ():
(async() => { console.time('concurrent') await Promise.all([f1(), f2(), f3()]) console.timeEnd('concurrent')
الخطأ رقم 5. الاستخدام غير السليم لـ Promise.race ()
Promise.race () لا يجعل كودك دائمًا أسرع.
قد يبدو غريباً ، لكنه حقاً. أنا لا أقول أن Promise.race () طريقة غير مجدية ، لكن يجب أن تفهم بوضوح سبب استخدامك لها.
على سبيل المثال ، يمكنك استخدام Promise.race () لتشغيل التعليمات البرمجية بعد حل أي من الوعود. لكن هذا لا يعني أن تنفيذ الكود باتباع الوعود سيبدأ مباشرة بعد حل أحدهم. سينتظر Promise.race () جميع الوعود لحلها ثم يصدر الدفق فقط:
const {promisify} = require('util') const sleep = promisify(setTimeout) async function f1() { await sleep(1000) } async function f2() { await sleep(2000) } async function f3() { await sleep(3000) } (async() => { console.time('race') await Promise.race([f1(), f2(), f3()]) })(); process.on('exit', () => { console.timeEnd('race')
الخطأ رقم 6. إساءة استخدام الوعود
الوعود تجعل التعليمات البرمجية أبطأ ، لذلك لا تسيء استخدامها.
غالبًا ما يتعين عليك رؤية المطورين الذين يستخدمون سلسلة طويلة. () لجعل التعليمات البرمجية الخاصة بهم تبدو أفضل. لن يكون لديك وقت لتغمض عينيك ، لأن هذه السلسلة تصبح طويلة جدًا. من أجل التحقق بصريًا من العواقب السلبية لمثل هذا الموقف ، من الضروري (علاوة على ذلك ، سأستخرج قليلاً من النص الأصلي من أجل وصف العملية بمزيد من التفصيل أكثر مما ورد في المقال - تقريبًا Trans):
1) قم بإنشاء ملف script.js بالمحتوى التالي (مع وعود إضافية):
new Promise((resolve) => {
2) افتح سطر الأوامر (لمستخدمي Windows: لفتح سطر الأوامر في المجلد مع الملف المطلوب ، مع الاستمرار على مفتاح Shift ، انقر بزر الماوس الأيمن ، حدد "فتح نافذة الأوامر") ، قم بتشغيل script.js باستخدام الأمر التالي (يجب تثبيت العقدة. شبيبة):
node --trace-events-enabled script.js
3) Node.js بإنشاء ملف سجل (في حالتي node_trace.1.txt) في المجلد مع البرنامج النصي ؛
4) افتح Chrome (لأنه يعمل فقط فيه) ، أدخل "chrome: // tracing" في شريط العناوين ؛
5) انقر فوق تحميل ، قم بتحميل ملف السجل الذي أنشأته Node.js ؛
6) افتح علامة التبويب وعد.
نرى شيئا مثل ما يلي:

الكتل الخضراء عبارة عن وعود ، يستغرق كل منها عدة ميلي ثانية لإكمالها. لذلك ، كلما زادت الوعود ، كلما تم تنفيذها.
نعيد كتابة script.js:
new Promise((resolve, reject) => { const user = { name: 'John Doe', age: 50, } if(user.age > 25) { resolve() } else { reject('Age is less than 25') } }).then(() => { console.log('Age is greater than 25') }).catch(e => { console.log(e.message) })
كرر "التتبع".
نرى ما يلي:

هناك عدد أقل من الكتل الخضراء (الوعود) ، مما يعني أنه تم تقليل وقت تنفيذ التعليمات البرمجية.
وبالتالي ، يجب عليك استخدام العديد من الوعود فقط إذا كنت بحاجة إلى تنفيذ بعض التعليمات البرمجية غير المتزامنة.
شكرا لاهتمامكم أتمنى لك عطلة نهاية أسبوع لطيفة! سأكون سعيدا بأي تعليقات.