استخدام الوعود في جافا سكريبت

من وقت لآخر ننشر المواد التي تتعلق بطريقة أو بأخرى باستخدام الوعود في جافا سكريبت.


لماذا ينصب الكثير من الاهتمام على الوعود؟ نحن نعتقد أن النقطة الأساسية هي أن هذه التكنولوجيا مطلوبة جدًا ، ومن الصعب جدًا فهمها.

لذلك ، إذا كنت ترغب في فهم الوعود بشكل أفضل ، فإننا نقدم لك ترجمة للمقال التالي حول هذا الموضوع. يقول مؤلفه أنه كان يطور Java و PHP على مدى السنوات العشر الماضية ، ولكن طوال هذا الوقت كان يبحث باهتمام في JavaScript. في الآونة الأخيرة ، قرر الانخراط بجدية في شبيبة ، وأصبحت الوعود أول موضوع يثير اهتمامه.



نعتقد أن هذه المادة ستكون مثيرة للاهتمام للمطورين المبتدئين الذين يشعرون أنه على الرغم من أنهم يستخدمون الوعود ، إلا أنهم لا يفهمونها جيدًا. من الممكن أن قصة شخص ينظر إلى JavaScript بعين جديدة ويسعى إلى شرح للآخرين ما فهمه هو نفسه ، وليس بافتراض أن بعض الأشياء مفهومة للجميع ودون تفسير ، ستساعد المبتدئين في إتقان آليات JavaScript.

JavaScript من خلال عيون المبتدئين


قد يشعر أي شخص يبدأ الكتابة في جافا سكريبت بما يسمى "خارج المكان". يقول البعض أن JS هي لغة برمجة متزامنة ، ويقول البعض الآخر أنها غير متزامنة. يسمع مبتدئ عن التعليمات البرمجية التي تحظر الخيط الرئيسي ، وعن التعليمات البرمجية التي لا تمنعه ​​، وعن أنماط التصميم القائمة على الأحداث ، وعن دورة حياة الأحداث ، وعن مجموعة مكالمات الوظائف ، وعن قائمة انتظار الأحداث وصعودها ، حول الملفات المتعددة. يتعلم أن هناك أشياء مثل Babel و Angular و React و Vue وعدد لا يحصى من المكتبات الأخرى. إذا كنت قد تعرفت على نفسك للتو في مثل هذا "المبتدئ" - فلا تقلق بشأن ذلك. أنت لست الأول ولا الأخير. حتى أن هناك مصطلح لهذا - ما يسمى بـ "تعب JavaScript". تحدث Lucas F Costa عن حق في هذا الموضوع: "إن إرهاق جافا سكريبت هو شيء يمكن ملاحظته عندما يستخدم الأشخاص أدوات لا يحتاجون إليها لحل المشكلات التي ليست لديهم ."

ولكن دعونا لا نتحدث عن أشياء حزينة. لذا ، فإن JavaScript هي لغة برمجة متزامنة ، والتي بفضل آلية رد الاتصال ، تسمح لك باستدعاء الوظائف بنفس الطريقة كما في اللغات غير المتزامنة.

قصة بسيطة عن الوعود


كلمة الوعد تترجم إلى الوعد. عناصر الوعد في البرمجة ، والتي نسميها "الوعود" ، تشبه إلى حد بعيد الوعود المعتادة التي يعطيها الناس بعضهم البعض في الحياة الواقعية. لذلك دعونا نتحدث عن هذه الوعود أولاً.

على ويكيبيديا ، يمكنك العثور على التعريف التالي لكلمة "وعد": "الالتزام ، موافقة شخص ما على تنفيذ شيء ما ، أو على العكس من ذلك ، عدم القيام". في قاموس Ozhegov ، "الوعد" هو "التزام طوعي بفعل شيء ما".

فماذا نعرف عن الوعود؟

  1. يمنحك الوعد ضمانًا بأن شيئًا ما سيتم القيام به. لا يهم من يفعل ذلك بالضبط: الشخص الذي قدم الوعد ، أو شخص آخر ، بناء على طلب الشخص الذي قدم الوعد. الوعد يعطي الثقة في شيء ما ، بناءً على هذه الثقة يمكن للشخص الذي تلقى الوعد ، على سبيل المثال ، وضع بعض الخطط.
  2. الوعد يمكن أن يتحقق أو لا.
  3. إذا تم الوفاء بالوعد ، ونتيجة لذلك ، تتوقع شيئًا يمكنك استخدامه في المستقبل لتنفيذ أي إجراءات أو تنفيذ أي خطط.
  4. إذا لم يتم الوفاء بالوعد ، فستحتاج إلى معرفة سبب عدم قدرة الشخص الذي قدمه على الوفاء به. بعد أن تعرف سبب ما حدث وستتأكد من عدم الوفاء بالوعد ، يمكنك التفكير في ما يجب القيام به بعد ذلك ، أو كيفية التعامل مع الموقف.
  5. بعد أن وعدت بشيء ، كل ما لديك هو نوع من الضمان. لا يمكنك الاستفادة مما وعدت به على الفور. يمكنك أن تحدد بنفسك ما يجب عليك فعله إذا تم الوفاء بالوعد (وبالتالي ، ستحصل على الوعد) ، وما عليك فعله إذا تبين أنه تم كسره (في هذه الحالة ، تعرف سبب ما حدث ، وبالتالي يمكنك التفكير في خطة احتياطية للإجراءات )
  6. من المحتمل أن يختفي الشخص الذي قدم الوعد ببساطة. في مثل هذه الحالات ، من المفيد أن يتم ربط الوعد بنوع من الإطار الزمني. على سبيل المثال ، إذا لم يظهر الشخص الذي أعطاك الوعد في غضون 10 أيام ، يمكنك أن تفترض أن لديه بعض المشاكل وأنه خالف الوعد. ونتيجة لذلك ، حتى إذا نفذ الشخص الذي وعد الوعد في غضون 15 يومًا ، فلن يهم ، لذا فأنت تعمل بالفعل على الخطة البديلة ، وليس الاعتماد على الوعد.

انتقل الآن إلى JavaScript.

وعود جافا سكريبت


لدي قاعدة واحدة: عند القيام بجافا سكريبت ، أقرأ دائمًا الوثائق التي يمكن العثور عليها في MDN. يبدو لي أن هذا المورد يقارن بشكل إيجابي مع الآخرين في خصوصية ووضوح العرض. لذلك ، أثناء دراسة الوعود ، تعرفت على المواد ذات الصلة وجربت الشفرة من أجل التعود على تراكيب بناء الجملة الجديدة.

من أجل فهم الوعود ، تحتاج إلى التعامل مع شيئين رئيسيين. الأول هو خلق الوعود. والثاني هو معالجة النتائج التي أعادتها الوعود. على الرغم من أن معظم التعليمات البرمجية التي نكتبها تهدف إلى العمل مع الوعود التي تم إنشاؤها ، على سبيل المثال ، من قبل مكتبات معينة ، إلا أن الفهم الكامل لآليات عمل الوعود سيكون مفيدًا بلا شك. بالإضافة إلى ذلك ، بالنسبة للمبرمج الذي لديه بالفعل بعض الخبرة ، فإن معرفة كيفية إنشاء الوعود لا تقل أهمية عن معرفة كيفية العمل معهم.

خلق الوعود


إليك كيفية إنشاء الوعود:

new Promise( /* executor */ function(resolve, reject) { ... } ); 

يقبل المنشئ دالة تؤدي إجراءات معينة ، وقد أطلقنا عليها هنا executor . تأخذ هذه الوظيفة معلمتين - resolve reject ، وهما بدورهما وظائف. عادةً ما يتم استخدام الوعود لإجراء عمليات غير متزامنة أو تعليمات برمجية يمكنها حظر سلسلة المحادثات الرئيسية ، على سبيل المثال ، تلك التي تعمل مع الملفات ، وتجري مكالمات API ، وتجري استعلامات قاعدة البيانات ، وتتعامل مع I / O ، وما إلى ذلك. يتم تنفيذ مثل هذه العمليات غير المتزامنة في وظيفة executor . إذا اكتملت العملية غير المتزامنة بنجاح ، فسيتم إرجاع النتيجة المتوقعة من الوعد عن طريق استدعاء دالة resolve . يتم تحديد الحالة التي يتم فيها استدعاء هذه الوظيفة من قبل منشئ الوعد. وبالمثل ، عند حدوث خطأ ، يتم إرجاع المعلومات حول ما حدث عن طريق استدعاء دالة reject .

الآن بعد أن عرفنا ، بشكل عام ، كيفية إنشاء الوعود ، سنخلق وعدًا بسيطًا لفهم كل شيء بشكل أفضل.

 var keepsHisWord; keepsHisWord = true; promise1 = new Promise(function(resolve, reject) { if (keepsHisWord) {   resolve("The man likes to keep his word"); } else {   reject("The man doesnt want to keep his word"); } }); console.log(promise1); 

إليك ما سيخرجه هذا الرمز:


الوعد يحتوي على حالة (PromiseStatus) وقيمة (PromiseValue)

نظرًا لأن وعدنا يتم حله على الفور ، لا يمكننا التحقيق في حالته الأولية. لذلك ، دعونا ننشئ وعدًا جديدًا يحتاج إلى بعض الوقت من أجل الحل. أسهل طريقة للقيام بذلك هي باستخدام وظيفة setTimeout .

 promise2 = new Promise(function(resolve, reject) { setTimeout(function() {   resolve({     message: "The man likes to keep his word",     code: "aManKeepsHisWord"   }); }, 10 * 1000); }); console.log(promise2); 

في هذا الرمز ، يتم إنشاء وعد سيتم حله بالتأكيد في 10 ثوانٍ. هذا يتيح لنا الفرصة للنظر في حالة وعد غير مصرح به.


وعد لم يتم حله

بعد مرور 10 ثوانٍ ، سيتم حل الوعد. ونتيجة لذلك ، سيتم تحديث كل من PromiseStatus و PromiseValue وفقًا لذلك. كما ترون ، قمنا في هذا المثال بتغيير الوظيفة التي تم استدعاؤها عندما تم حل الوعد بنجاح ، والآن لا ترجع سلسلة عادية ، ولكن كائنًا. يتم ذلك من أجل توضيح القدرة على إرجاع هياكل البيانات المعقدة باستخدام وظيفة resolve .


تم حل الوعد بعد 10 ثوانٍ وإرجاع كائن

دعونا الآن نلقي نظرة على الوعد ، الذي قررنا عدم السماح به ، ولكن رفضه. للقيام بذلك ، نقوم بتعديل الرمز الذي تم استخدامه بالفعل في المثال الأول.

 keepsHisWord = false; promise3 = new Promise(function(resolve, reject) { if (keepsHisWord) {   resolve("The man likes to keep his word"); } else {   reject("The man doesn't want to keep his word"); } }); console.log(promise3); 

نظرًا لأننا لا نتعامل مع حالة رفض الوعد ، فسيتم عرض رسالة خطأ في وحدة تحكم المتصفح (يتم استخدام Google Chrome هنا). سنتحدث أكثر عن هذا أدناه.


الوعد المرفوض

الآن ، بعد تحليل جميع الأمثلة الثلاثة ، يمكننا أن نرى أنه يمكن أن تظهر ثلاث قيم مختلفة في PromiseStatus : pending (معلقة) ، resolved ( resolved ناجح) rejected (رفض). عندما يتم إنشاء الوعد ، في PromiseStatus سيكون pending ، وفي PromiseValue سيكون undefined . ستبقى هذه القيم حتى يتم حل الوعد أو رفضه. عندما يكون الوعد في حالة resolved أو rejected ، يطلق عليه الوعد settled . لقد انتقل هذا الوعد من حالة انتظار إلى دولة يكون فيها إما دولة resolved أو دولة rejected .

الآن بعد أن تعلمنا كيفية إنشاء الوعود ، يمكننا التحدث عن كيفية معالجة ما يعودون. من أجل معرفة ذلك ، نحتاج إلى فهم بنية كائن Promise .

كائن الوعد


وفقًا لوثائق MDN ، فإن كائن Promise هو نتيجة إكمال ناجح أو غير ناجح لعملية غير متزامنة.

يحتوي كائن Promise على طرق ثابتة وطرق نموذجية للكائن. يمكن استدعاء الطرق الثابتة بدون إنشاء مثيل للكائن ، وللاتصال بأساليب النموذج الأولي ، تحتاج إلى مثيل لكائن Promise . ضع في اعتبارك أن كلاً من الأساليب الثابتة والعادية تعيد كائنات Promise . هذا يجعل العمل أسهل.

methods طرق أساليب الكائن الوعد


لنتحدث أولاً عن طرق النموذج الأولي لكائن Promise . هناك ثلاث طرق من هذا القبيل. لا تنس أنه يمكن استدعاء هذه الأساليب في مثيل كائن Promise ، وأنهم أنفسهم يعيدون الوعود. بفضل كل هذه الأساليب ، يمكنك تعيين معالجات تستجيب للتغيرات في حالة الوعود. كما رأينا بالفعل ، عندما يتم إنشاء الوعد ، فإنه في حالة pending . عندما ينتقل الوعد إلى حالة تم resolved أو rejected ، سيتم استدعاء إحدى الطرق التالية على الأقل:

 Promise.prototype.catch(onRejected) Promise.prototype.then(onFulfilled, onRejected) Promise.prototype.finally(onFinally) 

فيما يلي رسم تخطيطي لعملية الوعد والأحداث التي تؤدي إلى استدعاء .catch .then و .catch . نظرًا لأن هذه الأساليب ترجع كائنات Promise ، يمكن تقييد مكالماتها ، وهذا ينعكس أيضًا في الرسم التخطيطي. إذا كان الوعد يستخدم طريقة .finally ، فسيتم استدعاؤه عندما ينتقل الوعد إلى الحالة settled ، بغض النظر عما إذا كان الوعد قد تم حله أو رفضه بنجاح.


مخطط عمل Promis (الصورة مأخوذة من هنا )

هنا قصة قصيرة. أنت طالب واطلب من والدتك شراء هاتف محمول. وتقول: "إذا كانت مدخراتنا أكثر من تكلفة الهاتف ، فسأشتريها لك". الآن رواية هذه القصة في جافا سكريبت.

 var momsPromise = new Promise(function(resolve, reject) { momsSavings = 20000; priceOfPhone = 60000; if (momsSavings > priceOfPhone) {   resolve({     brand: "iphone",     model: "6s"   }); } else {   reject("We donot have enough savings. Let us save some more money."); } }); momsPromise.then(function(value) { console.log("Hurray I got this phone as a gift ", JSON.stringify(value)); }); momsPromise.catch(function(reason) { console.log("Mom coudn't buy me the phone because ", reason); }); momsPromise.finally(function() { console.log(   "Irrespecitve of whether my mom can buy me a phone or not, I still love her" ); }); 

إليك ما سيخرجه هذا الرمز:


أمي لم تفي بوعدها

إذا قمنا بتغيير قيمة momsSavings المتغيرة إلى 200.000 ، فستكون الأم قادرة على شراء هدية لابنها. في هذه الحالة ، سيؤدي الرمز أعلاه إلى إخراج ما يلي.


أمى الوعد

الآن دعونا نتخيل أن الكود المعني مصمم كمكتبة ، ونحن نستخدم هذه المكتبة. لنتحدث عن الاستخدام الفعال .catch و.

نظرًا .then يمكن تعيين طريقة onFulfilled لكل من معالج onFulfilled الذي يتم استدعاؤه عند حل الوعد بنجاح onRejected الذي يتم استدعاؤه عند رفض الوعد ، بدلاً من استخدام كل من طريقة .catch وطريقة .catch ، يمكننا تحقيق نفس التأثير باستخدام واحد فقط طريقة. إليك ما قد يبدو عليه:

 momsPromise.then( function(value) {   console.log("Hurray I got this phone as a gift ", JSON.stringify(value)); }, function(reason) {   console.log("Mom coudn't buy me the phone because ", reason); } ); 

هذا مثال عملي ، ولكن من أجل منع قراءة التعليمات البرمجية ، من الأفضل استخدام طرق .catch و .catch بدلاً من واحد .catch عالمي.

لكي يتم تشغيل هذه الأمثلة في متصفح ، وبشكل خاص في Google Chrome ، حاولت تجنب التبعيات الخارجية. من أجل فهم أفضل لما سنأخذه في الاعتبار لاحقًا ، دعنا ننشئ وظيفة تُرجع وعدًا ، والذي يتم حله أو رفضه بشكل عشوائي. سيسمح لنا هذا بتجربة سيناريوهات مختلفة للعمل مع الوعود. من أجل فهم ميزات الوظائف غير المتزامنة ، سنضع تأخيرات عشوائية في وعودنا. نظرًا لأننا بحاجة إلى أرقام عشوائية ، فإننا نقوم بإنشاء دالة تُرجع رقمًا عشوائيًا بين x و y . هنا هي الوظيفة.

 function getRandomNumber(start = 1, end = 10) { //,      start  end >=1  end > start return parseInt(Math.random() * end) % (end-start+1) + start; } 

الآن قم بإنشاء دالة تقوم بإرجاع الوعود. promiseTRRARNOSG عليه promiseTRRARNOSG . يشير اسم هذه الوظيفة إلى promiseThatResolvesRandomlyAfterRandomNumnberOfSecondsGenerator ، أي أنها عبارة عن مولد للوعود التي يتم حلها أو رفضها بشكل عشوائي بعد عدد عشوائي من الثواني. ستعمل هذه الوظيفة على إنشاء وعد سيتم السماح به أو رفضه بعد فترة زمنية عشوائية بين 2 و 10 ثوانٍ. للسماح بوعد أو رفضه عشوائيًا ، نحصل على رقم عشوائي بين 1 و 10. إذا كان هذا الرقم أكثر من 5 ، فسيُسمح بوعد الوعد ، إذا لم يكن كذلك ، فسيتم رفضه.

 function getRandomNumber(start = 1, end = 10) { //,      start  end >=1  end > start return (parseInt(Math.random() * end) % (end - start + 1)) + start; } var promiseTRRARNOSG = (promiseThatResolvesRandomlyAfterRandomNumnberOfSecondsGenerator = function() { return new Promise(function(resolve, reject) {   let randomNumberOfSeconds = getRandomNumber(2, 10);   setTimeout(function() {     let randomiseResolving = getRandomNumber(1, 10);     if (randomiseResolving > 5) {       resolve({         randomNumberOfSeconds: randomNumberOfSeconds,         randomiseResolving: randomiseResolving       });     } else {       reject({         randomNumberOfSeconds: randomNumberOfSeconds,         randomiseResolving: randomiseResolving       });     }   }, randomNumberOfSeconds * 1000); }); }); var testProimse = promiseTRRARNOSG(); testProimse.then(function(value) { console.log("Value when promise is resolved : ", value); }); testProimse.catch(function(reason) { console.log("Reason when promise is rejected : ", reason); }); //             ,    .     ,  - . for (i=1; i<=10; i++) { let promise = promiseTRRARNOSG(); promise.then(function(value) {   console.log("Value when promise is resolved : ", value); }); promise.catch(function(reason) {   console.log("Reason when promise is rejected : ", reason); }); } 

قم بتشغيل هذا الرمز في وحدة تحكم المتصفح لمعرفة كيفية عمل الوعود المسموح بها والمرفوضة. بعد ذلك ، سنتحدث عن كيفية إنشاء العديد من الوعود والتحقق من نتائج تنفيذها ، باستخدام آليات أخرى.

طرق ثابتة لكائن وعد


هناك أربع طرق ثابتة لكائن Promise .

فيما يلي طريقتان - Promise.reject(reason) و Promise.resolve(value) ، والتي تتيح لك إنشاء وعود مرفوضة ومسموح بها على التوالي.

إليك كيفية العمل باستخدام طريقة Promise.reject ، التي تخلق وعودًا مرفوضة.

 var promise3 = Promise.reject("Not interested"); promise3.then(function(value){ console.log("This will not run as it is a rejected promise. The resolved value is ", value); }); promise3.catch(function(reason){ console.log("This run as it is a rejected promise. The reason is ", reason); }); 

فيما يلي مثال باستخدام طريقة Promise.resolve التي تخلق وعود تم حلها بنجاح.

 var promise4 = Promise.resolve(1); promise4.then(function(value){ console.log("This will run as it is a resovled promise. The resolved value is ", value); }); promise4.catch(function(reason){ console.log("This will not run as it is a resolved promise", reason); }); 

وتجدر الإشارة إلى أن الوعد قد يكون له عدة معالجات. على سبيل المثال ، بناءً على المثال السابق ، يمكنك الحصول على الرمز الموضح أدناه.

 var promise4 = Promise.resolve(1); promise4.then(function(value){ console.log("This will run as it is a resovled promise. The resolved value is ", value); }); promise4.then(function(value){ console.log("This will also run as multiple handlers can be added. Printing twice the resolved value which is ", value * 2); }); promise4.catch(function(reason){ console.log("This will not run as it is a resolved promise", reason); }); 

إليك ما يعرضه في وحدة تحكم المتصفح:


باستخدام .then متعددة عند العمل مع Promise

تم تصميم الطريقتين التاليتين ، Promise.all و Promise.race ، للعمل مع مجموعات من الوعود. إذا كان من الضروري ، لحل مشكلة معينة ، معالجة عدة وعود ، فمن الأنسب وضع هذه الوعود في مصفوفة ، ثم تنفيذ الإجراءات اللازمة معها. من أجل فهم جوهر الأساليب المذكورة هنا ، لن نتمكن من استخدام promiseTRRARNOSG المناسب لوظيفة promiseTRRARNOSG ، نظرًا لأن نتيجة عملها تعتمد كثيرًا على إرادة الحالة. سيكون أكثر ملاءمة لنا أن نستخدم شيئًا ينتج وعودًا أكثر قابلية للتنبؤ بها ، مما سيسمح لنا بفهم سلوكهم. لذلك ، سننشئ وظيفتين جديدتين. واحد منهم ( promiseTRSANSG ) سيخلق وعودًا يتم حلها بعد n ثانية ، والثاني ( promiseTRJANSG ) - وعود تم رفضها بعد n ثانية.

 var promiseTRSANSG = (promiseThatResolvesAfterNSecondsGenerator = function( n = 0 ) { return new Promise(function(resolve, reject) {   setTimeout(function() {     resolve({       resolvedAfterNSeconds: n     });   }, n * 1000); }); }); var promiseTRJANSG = (promiseThatRejectsAfterNSecondsGenerator = function( n = 0 ) { return new Promise(function(resolve, reject) {   setTimeout(function() {     reject({       rejectedAfterNSeconds: n     });   }, n * 1000); }); }); 

سنستخدم الآن هذه الوظائف لفهم ميزات أسلوب Promise.all .

▍ طريقة Promise.all


من وثائق MDN ، يمكنك معرفة أن طريقة Promise.all(iterable) تُرجع وعدًا سيتم حله عندما يتم حل جميع الوعود التي تم تمريرها كوسيطة قابلة iterable ، أو عندما لا تحتوي هذه الوسيطة على وعود. سيتم رفض هذا الوعد إذا تم رفض أي من الوعود المحولة.
دعونا نلقي نظرة على بعض الأمثلة.

المثال رقم 1


سيتم السماح بجميع الوعود هنا. هذا السيناريو هو الأكثر شيوعًا.

 console.time("Promise.All"); var promisesArray = []; promisesArray.push(promiseTRSANSG(1)); promisesArray.push(promiseTRSANSG(4)); promisesArray.push(promiseTRSANSG(2)); var handleAllPromises = Promise.all(promisesArray); handleAllPromises.then(function(values) { console.timeEnd("Promise.All"); console.log("All the promises are resolved", values); }); handleAllPromises.catch(function(reason) { console.log("One of the promises failed with the following reason", reason); }); 

إليك ما سيخرجه هذا الرمز إلى وحدة التحكم:


جميع الوعود مسموح بها

بعد تحليل نتائج هذا المثال ، يمكن عمل ملاحظتين مهمتين.

أولاً ، الوعد الثالث ، الذي يستغرق حله ثانيتين ، يكتمل قبل الثاني ، ولكن ، كما يمكن رؤيته من الإخراج الذي تم إنشاؤه بواسطة الرمز ، يتم الحفاظ على ترتيب الوعود في الصفيف.

ثانيًا ، تحتوي الشفرة على موقّت يُستخدم لمعرفة الوقت المستغرق لتنفيذ تعليمات Promise.all .

إذا تم تنفيذ الوعود بالتسلسل ، فإن وقت تنفيذ هذه التعليمات سيكون 7 ثوانٍ (1 + 4 + 2). ومع ذلك ، يخبرنا المؤقت أن العملية بأكملها تستغرق 4 ثوان إذا تقريبنا النتيجة. هذا دليل على أن جميع الوعود تنفذ بالتوازي.

المثال رقم 2


ضع في اعتبارك الآن الحالة عندما لا تكون هناك وعود في الصفيف التي تم تمريرها إلى Promise.all. أعتقد أن هذه هي حالة الاستخدام الأقل شيوعًا لهذه الميزة.

 console.time("Promise.All"); var promisesArray = []; promisesArray.push(1); promisesArray.push(4); promisesArray.push(2); var handleAllPromises = Promise.all(promisesArray); handleAllPromises.then(function(values) { console.timeEnd("Promise.All"); console.log("All the promises are resolved", values); }); handleAllPromises.catch(function(reason) { console.log("One of the promises failed with the following reason", reason); }); 

فيما يلي الإخراج الذي سينتج عن هذا الرمز:


استدعاء Promise.all وتمرير صفيف يحتوي على أي وعود لهذه الطريقة

نظرًا لعدم وجود وعود في الصفيف ، Promise.all على الفور تقريبًا.

المثال رقم 3


الآن دعونا نلقي نظرة على ما يحدث عندما يتم رفض أحد الوعود التي تم تمريرها إلى Promise.all .

 console.time("Promise.All"); var promisesArray = []; promisesArray.push(promiseTRSANSG(1)); promisesArray.push(promiseTRSANSG(5)); promisesArray.push(promiseTRSANSG(3)); promisesArray.push(promiseTRJANSG(2)); promisesArray.push(promiseTRSANSG(4)); var handleAllPromises = Promise.all(promisesArray); handleAllPromises.then(function(values) { console.timeEnd("Promise.All"); console.log("All the promises are resolved", values); }); handleAllPromises.catch(function(reason) { console.timeEnd("Promise.All"); console.log("One of the promises failed with the following reason ", reason); }); 

كما ترى من نتائج تنفيذ التعليمات البرمجية الموضحة أدناه ، يتوقف تنفيذ Promise.all بعد أول وعد مرفوض مع إخراج الرسالة التي يعطيها هذا الوعد.


يتوقف التنفيذ بعد الوعد الأول المرفوض

▍ طريقة Promise.race


تفيد MDN أن طريقة Promise.race(iterable) تُرجع وعدًا مسموحًا به أو مرفوضًا بقيمة أو سبب الرفض بعد أن يُسمح أو يُرفض أحد الوعود المرسلة على التوالي.

دعونا Promise.race أمثلة للعمل مع Promise.race .

المثال رقم 1


يظهر ما يحدث عندما يتم تمرير أحد الوعود إلى Promise.race يتم حلها قبل أي شخص آخر.

 console.time("Promise.race"); var promisesArray = []; promisesArray.push(promiseTRSANSG(4)); promisesArray.push(promiseTRSANSG(3)); promisesArray.push(promiseTRSANSG(2)); promisesArray.push(promiseTRJANSG(3)); promisesArray.push(promiseTRSANSG(4)); var promisesRace = Promise.race(promisesArray); promisesRace.then(function(values) { console.timeEnd("Promise.race"); console.log("The fasted promise resolved", values); }); promisesRace.catch(function(reason) { console.timeEnd("Promise.race"); console.log("The fastest promise rejected with the following reason ", reason); }); 

هذا ما يصل إلى وحدة التحكم بعد تنفيذ هذا المثال.


بروميس ، التي حلت بشكل أسرع من أي شخص آخر

يتم تنفيذ جميع الوعود هنا بالتوازي. يتم حل الوعد الثالث بعد ثانيتين. بمجرد حدوث ذلك ، يتم حل الوعد الذي أعادته Promise.race .

المثال رقم 2


الآن فكر في الموقف عندما تم رفض أحد الوعود التي تم تمريرها إلى Promise.race .

 console.time("Promise.race"); var promisesArray = []; promisesArray.push(promiseTRSANSG(4)); promisesArray.push(promiseTRSANSG(6)); promisesArray.push(promiseTRSANSG(5)); promisesArray.push(promiseTRJANSG(3)); promisesArray.push(promiseTRSANSG(4)); var promisesRace = Promise.race(promisesArray); promisesRace.then(function(values) { console.timeEnd("Promise.race"); console.log("The fasted promise resolved", values); }); promisesRace.catch(function(reason) { console.timeEnd("Promise.race"); console.log("The fastest promise rejected with the following reason ", reason); }); 

بعد تنفيذ هذا المثال ، سيصل ما يلي إلى وحدة التحكم:


الوعد رفض قبل أي شخص آخر

الوعود هنا ، كما في الأمثلة السابقة ، يتم تنفيذها بالتوازي. الوعد الرابع مرفوض بعد 3 ثوان. بمجرد حدوث ذلك ، يتم رفض الوعد الذي أعادته Promise.race .

مثال عام وتجارب


جمعت كل الأمثلة التي أخذناها في الاعتبار في هذه المادة في مكان واحد ، مما سيسهل تجربتها ، لاستكشاف سيناريوهات مختلفة للعمل مع الوعود. تم تصميم هذا الرمز ليتم تنفيذه في متصفح ، لذلك لا نستخدم هنا أي مكالمات API ، ولا نصل إلى عمليات الملف ، ولا نعمل مع قواعد البيانات. على الرغم من أن كل هذا يجد تطبيقًا في تطوير المشاريع الحقيقية ، إلا أنني أعتقد أن العمل مع هذه الآليات يمكن أن يصرفنا عن هدفنا الرئيسي - الوعود. واستخدام الوظائف البسيطة التي تحاكي التأخيرات الزمنية تعطي نتائج مماثلة ولا تثقل كاهلنا بتفاصيل إضافية.

من خلال استكشاف هذه الأمثلة بنفسك ، يمكنك تجربة الكود ، مع قيم المتغيرات ، ودراسة سيناريوهات مختلفة لاستخدام الوعود. على وجه الخصوص ، يمكنك استخدام مزيج من promiseTRJANSG ، و promiseTRRARNOSG promiseTRSANSG و promiseTRRARNOSG لمحاكاة الكثير من السيناريوهات لاستخدام الوعود ، والتي ستسمح لك بفهمها بشكل أفضل. بالإضافة إلى ذلك ، لاحظ أن استخدام الأمر console.time يتيح لك معرفة الوقت المطلوب لتنفيذ جزء معين من التعليمات البرمجية ، وعلى سبيل المثال ، لمعرفة ما إذا تم تنفيذ الوعود بالتوازي أو بالتتابع. هنا رابط لصفحة الجوهر مع الرمز. وبالمناسبة ، إذا كنت تريد ، ألق نظرة على مكتبة Bluebird ، التي تحتوي على بعض الطرق المثيرة للاهتمام للعمل مع الوعود.

الملخص


أقدم لك قائمة بالقواعد التي ألتزم بها عند العمل مع الوعود من أجل استخدامها بشكل صحيح.

  1. استخدم الوعود في المواقف التي تعمل فيها باستخدام رمز غير متزامن أو حظر.
  2. للتعامل مع موقف حل الوعد بنجاح ، استخدم طريقة .then ؛ للحالات التي يتم فيها رفض الوعد ، استخدم .catch .
  3. استخدم .catch و .catch في جميع الوعود.
  4. - , , .finally .
  5. , , , .
  6. , .
  7. Promise , , , .
  8. Promise.all , .

, , , .

! , , ?

- ,
- 10% :



:)

Source: https://habr.com/ru/post/ar418085/


All Articles