آموزش ویژگی های ECMAScript 6 (جلسه 37) : آموزش کار با Promise - قسمت 3

دسته بندی: آموزش
زمان مطالعه: 5 دقیقه
۳۰ مهر ۱۳۹۶

همونطور که اطلاع دارید در جلسه قبل مقدماتی در مورد Promise‌ها و نحوه کارکرد اونا توضیح دادیم. در این جلسه میخوایم بحث قول‌ها رو ادامه بدیم و نحوه ساخت و کار کردن با اونا در Javascript رو به شما آموزش بدیم.

نحوه ساخت Promise ها

راه استاندارد برای ساخت قول‌ها استفاده از new Promise می‌باشد که یک تابع مدیریت کننده رو دریافت میکنه و این تابع دو پارامتر دارد. هر دو پارامتر تابع هستند که یکی از اونا resolve و دیگری reject می‌باشد. اولین پارامتر که عموما اون رو بنام resolve میشناسن، تابعی هست که در زمان دریافت اطلاعات مورد نظر در آینده نزدیک، فراخوانی می‌شود و پارامتر دوم که reject نامیده می‌شود، تابعی است که در زمانی که Promise با اروری مواجه میشه و یا اینکه مقدار خاصی رو دریافت نکند، فراخوانی می‌شود.

کد زیر رو در نظر بگیرید:

var p = new Promise(function(resolve, reject) {  
   if (/* condition */) {
      resolve(/* value */);  // fulfilled successfully
   }
   else {
      reject(/* reason */);  // error, rejected
   }
});

همونطور که میبینید یک Promise ساختیم و اون رو درون متغیر p ذخیره کردیم. تابع مورد نظر با 2 پارامتر resolve و reject رو درون قول قرار دادیم. درون قول یک حلقه if-else قرار دادیم و زمانی که شرط نمونه مورد نظر true باشه، تابع resolve با مقدار مورد نظر فراخوانی میشه و اگر شرط false باشه، تابع reject یا دلیل ارور فراخوانی می‌شود.

قول‌ها از هم مجزا و مستقل هستند و هیچ تاثیری بر روی هم ندارند و شما نمیتونین حالت مربوط به اونا رو بصورت دستی تغییر بدین.

هر کدی که درون تابع درونی Promise قرار بگیره، سریعا اجرا میشه. مثلا کد زیر رو در نظر بگیرید:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');
});

میبینید که یک Console.log درون قول قرار دادیم و اگر Console رو ببینیم متوجه میشیم که سریعا این مقدار چاپ شده است. پس ممکنه با خودتون بگید که هدف این قول‌ها چه چیزی است. همونطور که قبلا هم بیان شد شما میتونین با استفاده از قول‌ها کدهای Asynchronous رو مدیریت کرده و با اونا مثل کدهای Synchronous رفتار کنید. مثلا فرض کنید که یک setTimeout قرار بدیم و بخوایم بعد از 2 ثانیه چیزی رو در خروجی چاپ کنیم. بدلیل این از setTimeout استفاده میکنیم تا رفتار کدهای Asynchronous یا غیرهمزمان رو شبیه سازی کنیم. برای اینکار بصورت زیر عمل میکنیم:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');

	setTimeout(function() {
		console.log('Timeout done');
	}, 2000);
});

میبینید که یک setTimeout قرار دادیم و میخوایم بعد از 2 ثانیه یک رشته در Console چاپ بشه. حالا بنظرتون چطور میتونیم کدی رو بعد از پایان رسیدن قول انجام بدیم؟ مثلا فرض کنید بخوایم زمانی که setTimeout کارش تموم شد و مقدار رو درون Console چاپ کرد، اون رو متوجه بشیم و کد دیگری رو بعد از اون اجرا کنیم. برای اینکار میتونیم پارامتر resolve که تعریف کردیم رو وارد کنیم و اون رو فراخوانی کنیم. بصورت زیر:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');

	setTimeout(function() {
		console.log('Timeout done');
		resolve();
	}, 2000);
});

میبینید که تابع resolve رو بعد از console.log فراخوانی کردیم. زمانی که تابع resolve رو درون Promise فراخوانی میکنید، باعث میشه تا متد then مربوط به Promise فراخوانی بشه و کدهای درون اون اجرا بشه. بصورت زیر:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');

	setTimeout(function() {
		console.log('Timeout done');
		resolve();
	}, 2000);
});

p.then(function() {
	console.log('Timeout Successful!');
});

میبینید که برای قولی که درون متغیر p ذخیره کردیم در خط 10 متد then رو به کار بردیم و یک تابع رو درون اون قرار دادیم. متد then زمانی که timeout به پایان برسه و تابع resolve فراخوانی بشه، اجرا میشه و رشته Timeout Successful در Console چاپ میشه.

شما میتونین یک رشته یا مقدار رو به همراه تابع resolve بفرستید و درون متد then از اون استفاده کنید. کد بالا رو میتونیم بصورت زیر هم بنویسیم:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');

	setTimeout(function() {
		console.log('Timeout done');
		resolve('Timeout Successfull!');
	}, 2000);
});

p.then(function(msg) {
	console.log(msg);
});

میبینید که به رشته ارسال شده توسط تابع resolve در متد then به راحتی دسترسی پیدا کرده و اون رو در Console چاپ کردیم. فرض کنید که بجای تابع resolve، تابع reject رو فراخوانی کنیم. با این کار، بجای متد then، متد catch فراخوانی میشه و کدهای درون اون اجرا میشه. کد زیر رو ببینید:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');

	setTimeout(function() {
		console.log('Timeout done');
		reject(new Error('Sample Error'));
	}, 3000);
});

p.catch(function(error) {
	console.error(error);
});

میبینید که درون setTimeout بعد از چاپ شدن رشته مورد نظر، تابع reject رو فراخوانی کردیم و یک ارور نمونه رو با اون ارسال کردیم. با اینکار متد catch در خط 10 اجرا شده و ارور فرستاده شده در Console نمایش داده میشه. خروجی در Console بعد از گذشت 3 ثانیه بصورت زیر خواهد بود:

شما میتونین بصورت همزمان از دو تابع resolve و reject استفاده کنید و در زمانهایی که تشخیص میدید اونا رو فراخوانی کنید. بصورت زیر:

var p = new Promise(function(resolve, reject) {
	console.log('Init Promise');

	setTimeout(function() {
		console.log('Timeout done');
		if(true) {
			resolve('Timeout Successfull!');
		} else {
			reject(new Error('Sample Error'));
		}
	}, 2000);
});

p.then(function(msg) {
	console.log(msg);
});

p.catch(function(error) {
	console.error(error);
});

میبینید که یک شرط قرار دادیم و زمانی که true باشه resolve و در غیر این صورت reject صدا زده میشه. بعد از اون هم از متدهای then و catch استفاده کردیم. این متدها در مواقع مورد نیاز بصورت اتوماتیک اجرا میشن. شما میتونین بجای جدا نوشتن متدهای then و catch اونا رو پشت سر هم نیز قرار بدین. بصورت زیر:

p.then(function(msg) {
	console.log(msg);
}).catch(function(error) {
	console.error(error);
});

میبینید که اونا رو پشت سر هم قرار دادیم. نتیجه همانند حالت قبل خواهد بود. همچنین میشه برای متد then دو تابع رو بعنوان آرگومان قرار بدیم. با این کار آرگومان اول در زمان resolve و آرگومان دوم در زمان reject اجرا خواهد شد. بصورت زیر:

p.then(function(msg) {
	console.log(msg);
}, function(error) {
	console.error(error);
});

کد زیر هم همانند کدهای قبل می‌باشد و میبینید که خوانایی بالاتری دارد. از هر کدام که خواستید میتونین استفاده کنید. همچنین اگر یک Promise یک قول دیگه رو با استفاده از تابع resolve یا reject برگشت بده، میتونین متدهای catch و then بیشتری رو پشت سر هم قرار بدین.

در جلسه بعد با ادامه Promise‌ها در خدمتتون خواهیم بود.

موفق و پیروز باشید.

یا علی

چه امتیازی به این مقاله می دید؟
نویسنده محمد اسفندیاری
بسیار به طراحی وب علاقمندم و به سرعت در حال یادگیری تمام مباحث پیشرفته هستم و دوست دارم که به دیگران هم یاد بدهم.

جلسات دوره

نظرات کاربران

علیرضا بابایی

سلام
تا اینجای این مجموعه همراه بودم ؛ ولی با این مطلب خیلی حال کردم ، خیلی ساده توضیح دادید ، سایت های دیگه خیلی میپچوندن ، دمت گرم!

نیاز به لاگین

برای ارسال دیدگاه و یا پرسیدن سوال خود در این قسمت، باید در سایت لاگین شوید.