Promiseها در جاوااسکریپت – بخش اول

10 دی

جاوااسکریپت از جمله زبان‌هایی است که اتفاقات غیر همزمان (asynchronous) در آن معمول و متداول است. مثلا وقتی یک درخواست به سرور می‌فرستید جاوااسکریپت منتظر نمی‌ماند تا پاسخ آن دریافت شود. بلکه به اجرای خط به خط برنامه ادامه می‌دهد. اما این همیشه مطلوب نیست. بعضی اوقات لازم است تا از جاوااسکریپت قول بگیریم که بعد از مشخص شدن تکلیف اجرای یک دستور غیر همزمان کاری را انجام دهد. این‌جاست که راه Promiseها به قضیه باز می‌شود. دنیای برنامه‌نویسی غیر هم‌زمان دنیای مرموز و گاها دشواری است. پس بیایید یکی از بهترین مقالات را در این زمینه مرور کنیم. لینک اصلی این مقاله را در انتهای مطلب برایتان می‌گذارم تا در صورت تمایل سری به آن بزنید.

در حال حاضر یکی از این سه دسته هستید:

مفهوم Promiseها در جاوااسکریپت

جاوااسکریپت تک‌رشته (Single threaded) است. یعنی دو تکه کد را هم‌زمان اجرا نمی‌کند. پس کدها یکی پس از دیگری اجرا می‌شوند. بنابراین وقتی که جاوااسکریپت مشغول کاری است، تغییر در استایل‌ها، انجام درخواست‌های کاربران، پردازش المان‌های صفحه، ارسال فرم‌ها و … آن کار قبلی جاوااسکریپت را به تعویق می‌اندازد. در حالی که ما به عنوان یک انسان تک رشته نیستیم. می‌توانیم با چند انگشت تایپ کنیم یا هم‌زمان که رانندگی می‌کنیم صحبت کنیم. تنها مورد تک رشته شدن ما وقتی است که عطسه می‌کنیم! خیلی بد است! مخصوصا وقتی داریم حین رانندگی صحبت می‌کنیم. کد آغشته به عطسه هم به همان مقدار بد است!

احتمالا برای خلاصی از این مساله از eventها و callbackها استفاده می‌کنید:

var img1 = document.querySelector('.img-1');

img1.addEventListener('load', function() {
  // Eyvalll aks load shod!
});

img1.addEventListener('error', function() {
  // Poof be fana raft!
});

این کد بدی نیست. ما عکس را می‌گیریم، چند listener تعریف می‌کنیم و جاوااسکریپت به کارهای پردازشی خود ادامه می‌دهد تا نهایتا یکی از listenerها فراخوانی شود. اما در این‌جا ممکن است قبل از تعریف listenerها اتفاق مورد نظر ما (در اینجا لود شدن عکس) اتفاق بیفتد. بنابراین باید از خصوصیت complete عکس‌ها استفاده کرده و به شکل زیر کد را تغییر دهیم:

var img1 = document.querySelector('.img-1');

function loaded() {
  // Eyvalll aks load shod!
}

if (img1.complete) {
  loaded();
}
else {
  img1.addEventListener('load', loaded);
}

img1.addEventListener('error', function() {
  // Poof be fana raft!
});

این کد، عکس‌هایی که قبل از تعریف listener خطا (خط ۱۴)، دچار خطا شوند را تشخیص نمی‌دهد. متاسفانه DOM نیز راهی برای تشخیص آن در اختیار ما قرار نداده است. تازه این ماجرا برای لود یک عکس است. حالا اگر بخواهیم مجموعه‌ای از عکس‌ها را لود کنیم قضیه پیچیده‌تر هم می‌شود.

Eventها همیشه بهترین راه‌حل نیستند!

Eventها وقتی عالی هستند که بخواهیم یک اتفاق را بارها تکرار کنیم. مثلا کلیدی را فشار دهیم یا کلیک کنیم. در این حالت خیلی اهمیت نمی‌دهیم که قبل از تعریف listener چه اتفاقی افتاده است. در مورد موفقیت یا عدم موفقیت یک رویداد غیر همزمان چیزی شبیه به کد زیر مطلوب ما است:

img1.ageLoadShodInoFarakhaniKon(function() {
  // load shod
}).ammaAgeLoadNashod(function() {
  // load nashod
});

// va…
ageHameyeInaLoadShodan([img1, img2]).inoSedaBezan(function() {
  // Hamegi load shodan!
}).ammaAgeYeMoshkeliPishOmad(function() {
  // Yeki ya chanta az aksa load nashod!
});

این دقیقا چیزی هست که Promiseها انجام می‌دهند؛ البته با نامگذاری بهتر!

در اصل Promiseها شباهت‌های زیادی به Eventها دارند. البته با تفاوت‌های زیر:

این موارد به شدت برای برنامه‌نویسی غیر همزمان مفید هستند. زیرا دیگر نگران زمان دقیق اتفاق افتادن رویداد نیستید. در عوض روی تصمیم‌های مبتنی بر نتیجه رویداد کار می‌کنید.

چند اصطلاح در مورد Promiseها

یک Promise می‌تواند یکی از حالت‌های زیر را داشته باشد:

همچنین به Objectهایی که شبه-Promise باشند، یعنی دارای متد then باشند، tenable گفته می‌شود؛ به این معنی که این Objectها قابلیت تبدیل به Promiseهای واقعی را دارند.

قبل از این‌که Promiseها به صورت رسمی به جاوااسکریپت راه پیدا کنند، کتابخانه‌هایی برای اضافه کردن این قابلیت به کد وجود داشت که از جمله‌ی این‌ها عبارتند از:

همه‌ی کتابخانه‌های بالا از یک رفتار استاندارد شده به اسم +Promises/A استفاده می‌کنند. اگر کاربر jQuery باشید، حتما می‌دانید که این کتابخانه نیز از مفهوم مشابهی به اسم  Deferred استفاده می‌کند که البته با استاندارد +Promise/A سازگار نیست و باعث می‌شود اندکی متفاوت و کارایی آن اندکی کم‌تر باشد. با وجود این‌که همه‌ی کتابخانه‌های Promise از مفهوم استاندارد شده‌ی مشابهی استفاده می‌کنند اما نحوه‌ی کاربرد آن‌ها با یکدیگر متفاوت است. Promiseها در جاوااسکریپت از لحاظ نحوه‌ی کاربرد شبیه به کتابخانه‌ی RSVP.js است.

در بخش بعدی مقاله، اجزای Promise را با جزئیات بیش‌تری مورد بررسی قرار داده و یک پروژه فرضی را شروع کرده و با Promiseها جلو می‌بریم. اگر می‌خواهید به اصل مقاله دسترسی داشته باشید اینجا کلیک کنید.

10 دی دسته‌هاجاوااسکریپت برچسب‌هاPromise و جاوااسکریپت

Promiseها در جاوااسکریپت - بخش اول

جاوااسکریپت از جمله زبان‌هایی است که اتفاقات غیر همزمان (asynchronous) در آن معمول و متداول است. مثلا وقتی یک درخواست به سرور می‌فرستید جاوااسکریپت منتظر نمی‌ماند تا پاسخ آن دریافت شود. بلکه به اجرای خط به خط برنامه ادامه می‌دهد. اما این همیشه مطلوب نیست. بعضی اوقات لازم است تا از جاوااسکریپت قول بگیریم که بعد از مشخص شدن تکلیف اجرای یک دستور غیر همزمان کاری را انجام دهد. این‌جاست که راه Promiseها به قضیه باز می‌شود. دنیای برنامه‌نویسی غیر هم‌زمان دنیای مرموز و گاها دشواری است. پس بیایید یکی از بهترین مقالات را در این زمینه مرور کنیم.

10 دی دسته‌هاجاوااسکریپت برچسب‌هاجاوااسکریپت

10 متد مفید جاوااسکریپت در رابطه با آرایه‌ها

سلام دوستان. امیدوارم حالتون خوب باشه. در موقع کار کردن با جاوااسکریپت یکی از مواردی که زیاد استفاده می‌شه آرایه‌ها هستند و برای کار کردن با آرایه‌ها باید بتونید اون‌ها رو به شکل دلخواهتون دست‌کاری کنید. در این‌جا مقاله‌ای رو باهم مرور می‌کنیم که 10 متد مفید و مهم رو برای کار کردن با آرایه‌ها بررسی و با مثال بیان کرده. البته ممکن هست که بعضی جاها رو با توضیح بیش‌تر یا به شکل متفاوتی بیان کنم. لینک اصلی مقاله رو هم براتون آخر مقاله می‌ذارم.

10 دی دسته‌هاجاوااسکریپت برچسب‌هاPromise و جاوااسکریپت

Promiseها در جاوااسکریپت - بخش چهارم (آخر)

در این بخش از مقاله که بخش پایانی سری مقالات Promise‌ها است پروژه‌ای که تعریف کرده بودیم را تکمیل می‌کنیم و نکات ارزشمندی پیرامون استفاده‌ی حرفه‌ای از Promiseها بیان می‌کنیم. با من همراه باشید.

10 دی دسته‌هاجاوااسکریپت برچسب‌هاPromise و جاوااسکریپت

Promiseها در جاوااسکریپت - بخش سوم

در این بخش به مدیریت خطای Promiseها می‌پردازیم. اگر این سری مقاله را از ابتدا پیگیری نکرده‌اید پیشنهاد می‌کنم از بخش اول شروع کنید.