فهم وعود JavaScript

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

مقدمة للوعود

عادة ما يتم تعريف الوعد على أنهوكيل لقيمة ستصبح متاحة في النهاية.

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

على الرغم من أنها كانت موجودة منذ سنوات ، إلا أنها تم توحيدها وتقديمها فيES2015، والآن تم استبدالها فيES2017بواسطةوظائف غير متزامنة.

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

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

بمجرد أن يتم استدعاء الوعد ، سيبدأ فيحالة معلقة. هذا يعني أن وظيفة المتصل تواصل التنفيذ ، بينما تنتظر الوعد بالقيام بمعالجتها الخاصة ، وإعطاء وظيفة المتصل بعض الملاحظات.

في هذه المرحلة ، تنتظر وظيفة المتصل إما أن تعيد الوعد في ملفدولة حسمها، أو فيدولة مرفوضة، لكنتستمر الوظيفة في تنفيذها بينما ينجح الوعد.

أي JS API تستخدم الوعود؟

بالإضافة إلى التعليمات البرمجية الخاصة بك وكود المكتبة ، يتم استخدام الوعود بواسطة واجهات برمجة تطبيقات الويب الحديثة القياسية مثل:

من غير المحتمل أن تجد نفسك في JavaScript الحديثليسباستخدام الوعود ، فلنبدأ في الغوص فيها مباشرةً.


خلق الوعد

يعرض Promise API مُنشئ Promise ، والذي تقوم بالتهيئة باستخدامهnew Promise():

let done = true

const isItDoneYet = new Promise((resolve, reject) => { if (done) { const workDone = ‘Here is the thing I built’ resolve(workDone) } else { const why = ‘Still working on something else’ reject(why) } })

كما ترون الوعد يتحقق منdoneمتغير عالمي ، وإذا كان هذا صحيحًا ، فإننا نعيد الوعد النهائي ، وإلا وعدنا المرفوض

استخدامresolveوrejectيمكننا إعادة توصيل قيمة ، في الحالة المذكورة أعلاه ، نعيد سلسلة نصية ، لكنها قد تكون كائنًا أيضًا.


تستهلك الوعد

في القسم الأخير ، قدمنا كيف يتم إنشاء الوعد.

الآن دعونا نرى كيف يمكن أن يكون الوعدمستهلكأو استخدامها.

const isItDoneYet = new Promise()
//...

const checkIfItsDone = () => {
  isItDoneYet
    .then(ok => {
      console.log(ok)
    })
    .catch(err => {
      console.error(err)
    })
}

ادارةcheckIfItsDone()سوف ينفذisItDoneYet()وعد وسوف ننتظر حتى يتم حلها ، باستخدامthenرد الاتصال ، وإذا كان هناك خطأ ، فسيتم معالجته في ملفcatchأتصل مرة أخرى.


تقيد الوعود

يمكن أن يعود الوعد إلى وعد آخر ، ويخلق سلسلة من الوعود.

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

Fetch API هي آلية قائمة على الوعد والاتصالfetch()يعادل تحديد وعدنا باستخدامnew Promise().

مثال على تسلسل الوعود

const status = response => {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
  }
  return Promise.reject(new Error(response.statusText))
}

const json = response => response.json()

fetch(’/todos.json’) .then(status) .then(json) .then(data => { console.log(‘Request succeeded with JSON response’, data) }) .catch(error => { console.log(‘Request failed’, error) })

في هذا المثال نسميهfetch()للحصول على قائمة عناصر TODO منtodos.jsonتم العثور على ملف في جذر المجال ، وقمنا بإنشاء سلسلة من الوعود.

ادارةfetch()إرجاع أاستجابة، والتي لها العديد من الخصائص ، وضمن تلك التي نشير إليها:

  • status، وهي قيمة رقمية تمثل رمز حالة HTTP
  • statusText، رسالة الحالة ، وهيOKإذا نجح الطلب

responseلديه أيضاjson()الطريقة ، التي ترجع الوعد الذي سيحل بمحتوى الجسم الذي يتم معالجته وتحويله إلىجسون.

بالنظر إلى هذه المقدمات ، هذا ما يحدث: الوعد الأول في السلسلة هو وظيفة حددناها ، تسمىstatus()، التي تتحقق من حالة الاستجابة وإذا لم تكن استجابة ناجحة (بين 200 و 299) ، فإنها ترفض الوعد.

ستؤدي هذه العملية إلى تخطي سلسلة الوعد جميع الوعود المقيدة المدرجة وستنتقل مباشرة إلىcatch()بيان في الأسفل ، وتسجيلRequest failedنص مع رسالة الخطأ.

إذا نجح ذلك بدلاً من ذلك ، فإنه يستدعيjson()وظيفة حددناها. منذ الوعد السابق ، عندما نجح ، عادresponseكائن ، نحصل عليه كمدخل للوعد الثاني.

في هذه الحالة ، نعيد البيانات التي تمت معالجتها JSON ، لذا فإن الوعد الثالث يتلقى JSON مباشرةً:

.then((data) => {
  console.log('Request succeeded with JSON response', data)
})

ونقوم بتسجيله في وحدة التحكم.


معالجة الأخطاء

في المثال أعلاه ، في القسم السابق ، كان لدينا ملفcatchالتي تم إلحاقها بسلسلة الوعود.

عندما يفشل أي شيء في سلسلة الوعود ويثير خطأ أو يرفض الوعد ، ينتقل التحكم إلى الأقربcatch()بيان أسفل السلسلة.

new Promise((resolve, reject) => {
  throw new Error('Error')
}).catch(err => {
  console.error(err)
})

// or new Promise((resolve, reject) => { reject(‘Error’) }).catch(err => { console.error(err) })

أخطاء متتالية

إذا كان داخل ملفcatch()قمت برفع خطأ ، يمكنك إلحاق ثانيةcatch()للتعامل معها ، وما إلى ذلك.

new Promise((resolve, reject) => {
  throw new Error('Error')
})
  .catch(err => {
    throw new Error('Error')
  })
  .catch(err => {
    console.error(err)
  })

تنظيم الوعود

Promise.all()

إذا كنت بحاجة إلى مزامنة وعود مختلفة ،Promise.all()يساعدك على تحديد قائمة الوعود ، وتنفيذ شيء ما عندما يتم حلها جميعًا.

مثال:

const f1 = fetch('/something.json')
const f2 = fetch('/something2.json')

Promise.all([f1, f2]) .then(res => { console.log(‘Array of results’, res) }) .catch(err => { console.error(err) })

المهمة إتلاف ES2015بناء الجملة يتيح لك القيام بذلك أيضًا

Promise.all([f1, f2]).then(([res1, res2]) => {
  console.log('Results', res1, res2)
})

أنت لا تقتصر على استخدامfetchبالتاكيد،أي وعد على ما يرام.

Promise.race()

Promise.race()يتم تشغيله بمجرد أن يتم حل أحد الوعود التي تمررها إليه ، ويتم تشغيل رد النداء المرفق مرة واحدة فقط مع حل نتيجة الوعد الأول.

مثال:

const promiseOne = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one')
})
const promiseTwo = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two')
})

Promise.race([promiseOne, promiseTwo]).then(result => { console.log(result) // ‘two’ })

الأخطاء الشائعة

خطأ نوع غير معلوم: غير محدد ليس وعدًا

إذا حصلت علىUncaught TypeError: undefined is not a promiseخطأ في وحدة التحكم ، تأكد من استخدامnew Promise()بدلا من مجردPromise()


المزيد من دروس js: