مقدمة
يمكن فهم كائن الوعد على أنه عملية يتم تنفيذها (غالبًا ما تستخدم للعمليات غير المتزامنة). بعد استخدام كائن الوعد ، يمكن تنظيم الكود بطريقة استدعاء سلسلة لجعل الكود أكثر سهولة. علاوة على ذلك ، لأن وجود طريقة مثل الوعد. كل ذلك ، يمكن أن يكون بسيطًا لأداء عمليات متعددة في نفس الوقت.
صعود الوعد هو أنه في مكالمات الطريقة غير المتزامنة ، غالبًا ما تحدث وظائف رد الاتصال واحدًا تلو الآخر. وقد أدى هذا الوضع إلى ظهور مشاكل هرم رد الاتصال. ليس فقط الكود صعبًا وليس جميلًا في الكتابة ، ولكنه يجعل من الصعب أيضًا على الأشخاص الذين يقرؤون الكود لفهم عندما تكون المشكلة معقدة.
كمثال:
db.save (البيانات ، الدالة (البيانات) {// القيام بشيء ... db.save (data1 ، الدالة (البيانات) {// افعل شيئًا ... db.save (data2 ، الدالة (البيانات) {// افعل شيئًا ... تم القيام به (data3) ؛ // return data}) ؛}) ؛}) ؛ لنفترض أن هناك قاعدة بيانات حفظ ، ويتطلب الطلب أن يتم حفظ البيانات ثلاث مرات في ثلاث جداول. ثم رمزنا يشبه الرمز أعلاه. ماذا علي أن أفعل إذا كانت هناك مشكلة في db.save الثانية في هذا الوقت؟ بناءً على هذا الاعتبار ، نحتاج إلى استخدام المنطق مثل try...catch كل طبقة من رد الاتصال. هذا هو مصدر كل الشر ، وهي أيضًا نقطة انتقاد على نطاق واسع في البداية.
عيب آخر هو أنه على افتراض عدم وجود تبعية أمامية وظهر بين الحفظات الثلاثة لدينا ، ما زلنا بحاجة إلى الانتظار حتى يتم تنفيذ الوظيفة السابقة قبل تنفيذ الخطوة التالية ، ولا يمكن موازنة المحفوظات الثلاثة ، ثم إعادة النتيجة المطلوبة بعد الحفظ الثلاثة. (أو يتطلب مهارات لتنفيذها)
لسوء الحظ ، عندما بدأت في المشاركة في العقدة لأول مرة ، كتبت الكثير من الجحيم مثل هذا.
في وقت لاحق ، لأنني ما زلت أكتب المزيد من التعليمات البرمجية الأمامية ، تلامست مع ES6 ووجدت أداة قوية لحل الهاوية رد الاتصال.
في الواقع ، قبل فترة طويلة من الوعد ES6 ، Q ، عندما قامت JJs و Bluebird ومكتبات أخرى ببناء عجلات الوعد الخاصة بها بناءً على معيار الوعد (راجع Promise/A+).
(قرأت مقالًا وأعتقد أنه من المنطقي. إنه يقول إنه يجب ألا تمتد كائنات محلية مدمجة. لا يمكن أن يكون هذا النهج موجهًا في المستقبل. لذا ، إليك نصيحة: كن حذرًا عند استخدام المكتبات التي تمتد على الوعد الأصلي.)
وتناقش فقط الوعد الأصلي هنا.
وعد ES6
وعد حالة الكائن
قبل شرح الوعد بالتفصيل ، دعونا أولاً نأخذ نظرية:
تنص مواصفات Promise/A+ على أن كائن الوعد هو آلة الحالة المحدودة.
لديها ثلاث ولايات:
1. pending (التنفيذ)
2. fulfilled (ناجح)
3. reject
عندما تكون pending هي الحالة الأولية ، fulfilled rejected هي الحالات النهائية (تشير الحالة النهائية إلى أن دورة حياة الوعد قد انتهت).
علاقة انتقال الدولة هي:
معلق-> الوفاء ، معلق-> رفض.
سيتم تشغيل الأحداث المختلفة (مثل أحداث التنفيذ الناجحة ، وأحداث التنفيذ الفاشلة ، وما إلى ذلك) كتحولات الدولة.
شكل الوعد
يبدو الوعد هكذا:
var الوعد = وعد جديد (وظيفة func (حل ، رفض) {// القيام بشيء ، ربما غير متزامن إذا (النجاح) {return desolve (data) ؛} else {return refect (data) ؛}}) ؛الوعد المتغير هنا هو مثيل لكائن الوعد.
عند إنشاء كائن الوعد ، سيتم تنفيذ المنطق في وظيفة func .
عندما تتم معالجة المنطق ولا توجد أخطاء ، فإن resolve الاتصال سوف يمرر القيمة إلى مكان خاص. أين هذا المكان الخاص؟ هذا هو ثم في الكود التالي. نستخدم وظيفة رد الاتصال في then لمعالجة النتيجة بعد resolve . على سبيل المثال ، في الكود أعلاه ، نقوم ببساطة بإخراج القيمة إلى وحدة التحكم. إذا كان هناك خطأ ، reject في وظيفة رد الاتصال الثانية then لمعالجة الخطأ.
تمشيا مع النظرية المذكورة أعلاه لآلة الحالة المحدودة ، نعلم أنه عند تنفيذ رمز وظيفة رد الاتصال في مُنشئ الوعد ، تكون الدولة pending ، fulfilled بالدولة بعد resolve ، والدولة reject بعد reject
وعد تدفق البيانات
ما سبق هو تدفق البيانات الأول للوعد.
الأمر المضحك هو أن طريقة الوعد then لا يزال بإمكانها إعادة كائن الوعد ، حتى نتمكن من استخدام التالي then القيام بنفس المعالجة.
وظائف رد الاتصال في البداية then حدد نوع كائن الوعد الأول then يعود.
على افتراض أن رد الاتصال الأول من الأول then لا يعيد كائن وعد ، فإن المتصل في الثانية then لا يزال كائن الوعد الأصلي ، باستثناء أن قيمة حلها تصبح قيمة الإرجاع لوظيفة رد الاتصال الأولى في الأول.
على افتراض أن وظيفة الاتصال الأولى then تقوم بوظيفة الاتصال الأولى بإرجاع كائن وعد ، والثاني then يصبح المتصل كائن الوعد الجديد هذا ، والثاني then ينتظر كائن الوعد الجديد لحل أو يرفض وتنفيذ رد الاتصال.
على الرغم من أنني قد نجحت قليلاً ، إلا أنني أشعر أنني ما زلت واضحًا جدًا حيال ذلك. هاها ~
إذا تمت مواجهة خطأ في أي مكان ، فسيتم تسليم الخطأ إلى وظيفة رد الاتصال الثانية then مع وظيفة رد الاتصال الثانية للتعامل معها. يمكن فهم أن الخطأ reject للخلف حتى تتم معالجته.
بالإضافة إلى ذلك ، يحتوي كائن الوعد أيضًا على طريقة catch ، والتي تقبل وظيفة رد الاتصال للتعامل مع الأخطاء.
الآن:
promise.catch (وظيفة (err) {// ear the err.})على افتراض أن معالجة الأخطاء متشابهة ، فإن هذه الطريقة يمكن أن تتعامل بشكل مركزي وموحد. لذلك لا تتطلب الطرق الأخرى رد اتصال ثانٍ ~
السيطرة على الوعود المتزامنة
الوعد له "طريقة ثابتة" - Promise.all . تقبل هذه الطريقة عنصرًا يمثل مجموعة من كائنات الوعد.
هذه الطريقة أيضا إرجاع كائن الوعد. إذا تم resolve جميع كائنات الوعد في الصفيف ، فسيتم استخدام القيم resolve كصفيف كقيمة resolve للكائن (كائن الوعد) لقيمة الإرجاع Promise.all then إذا تم reject أي وعد في الصفيف ، فإن قيمة reject هي قيمة reject قيمة الإرجاع Promise.all .
نقطة غامضة للغاية هي:
إن ترتيب قيمة resolve (كما ذكر أعلاه ، صفيف) يتلقاه وظيفة رد الاتصال الأول للطريقة التين then هو نفس ترتيب صفيف المعلمة في Promise.all .
هناك resolve طريقة مشابهة Promise.all Promise.race
تحويل كائنات أخرى إلى كائنات وعد
يمكن أن تعيد طريقة Promise.resovle كائن الوعد كمعلمة.
هناك حالتان:
على افتراض أنه .then توجد طريقة للمعلمة التي تم تمريرها ، فإن كائن الوعد الذي تم إرجاعه يصبح حالة resolve ، والقيمة resolve هي الكائن نفسه.
على افتراض أن المعلمة التي تم تمريرها لها طريقة then (تسمى الكائن thenable ) ، ثم يتم تغيير نوع هذا الكائن إلى الوعد ، ويصبح طريقته then Promise.prototype.then .
هل الوعد حلاً للاختلاف؟
أخيرًا ، اسمحوا لي أن أقول شيئًا مهمًا للغاية: وظيفة Promise هي حل مشكلة أهرامات رد الاتصال ، ولا تلعب بالفعل دورًا كبيرًا في التحكم في العملية غير المتزامنة. لاستخدام الوعد حقًا للسيطرة على العملية غير المتزامنة ، نحتاج أيضًا إلى استخدام وظيفة generator ES6. (على سبيل المثال ، تنفيذ مكتبة CO في TJ Master).
ومع ذلك ، سيكون لدى ES7 حل أكثر رهيبة: async/await ، وهو مشابه لـ CO ، ولكن لديه دعم أصلي. دعنا ننتظر ونرى.
لخص
ما سبق هو كل شيء عن الوعد الأصلي في JavaScript ES6. آمل أن يكون محتوى هذه المقالة مفيدًا للجميع في تعلم ES6. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة للتواصل.