برنامه نویسی

روش های بهتر برای استفاده از توابع async در جاوا اسکریپت

اگر اهل توسعه وب هستید، به احتمال 100% حداقل از برخی از توابع async استفاده کرده اید. روش های مختلفی برای استفاده از توابع async وجود دارد، مانند .then() و async/await. اما اگر به شما بگویم راه‌های بهتری برای استفاده از توابع async وجود دارد که می‌تواند زمان درخواست را تا نصف کاهش دهد، چه؟ 🤯
بله این درست است! زمان اجرا جاوا اسکریپت ویژگی های مختلفی را ارائه می دهد که ما معمولاً آنها را نمی شناسیم یا از آنها استفاده نمی کنیم. یکی از این ویژگی ها متدهای ثابت برای کلاس Promise است.
در این پست کوتاه وبلاگ به نحوه استفاده از این موارد برای بهبود فراخوانی تابع async خود خواهیم پرداخت.

Promise.all()

را Promise.all() متد یک وعده تکراری را به عنوان ورودی می گیرد و یک وعده واحد را برمی گرداند که به آرایه نتایج وعده های ورودی حل می شود. اگر هر یک از وعده‌های ورودی رد شود یا اگر یک وعده غیر قولی خطا کند، بلافاصله رد می‌کند و با روش رد اول رد می‌شود.

به عنوان مثال:

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve,reject)=>{
     setTimeout(resolve,100,'foo');
})
Promise.all([promise1,promise2,promise3]).then((values)=>{
     console.log(values);
})
// expected output Array [3,42,'foo']
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حال بیایید ببینیم چگونه می توانیم از آن برای سرعت بخشیدن به تماس های همگام خود استفاده کنیم:

اجرای متوالی در مقابل اجرای همزمان

به طور معمول، هنگام برقراری فراخوانی تابع ناهمزمان یکی پس از دیگری، هر درخواست توسط درخواست قبل از خود مسدود می شود، این الگو به عنوان الگوی “آبشار” نیز شناخته می شود، زیرا هر درخواست تنها زمانی می تواند شروع شود که درخواست قبلی مقداری داده را برگرداند.

الگوی اجرای متوالی

// Simulate two API calls with different response times
function fetchFastData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Fast data");
    }, 2000);
  });
}

function fetchSlowData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Slow data");
    }, 3000);
  });
}


// Function to demonstrate sequential execution
async function fetchDataSequentially() {
  console.log("Starting to fetch data...");

  const startTime = Date.now();

  // Start both fetches concurrently
  const fastData = await fetchFastData();
  const slowData = await fetchSlowData();

  const endTime = Date.now();
  const totalTime = endTime - startTime;

  console.log(`Fast data: ${fastData}`);
  console.log(`Slow data: ${slowData}`);
  console.log(`Total time taken: ${totalTime}ms`);
}
fetchDataSequentially()
/*
expected output:
Starting to fetch data...
Fast data: Fast data
Slow data: Slow data
Total time taken: 5007ms
*/
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا یک نمودار برای تجسم بهتر است
اجرای متوالی

استفاده كردن Promise.all() ما می‌توانیم همه درخواست‌ها را به یکباره خاموش کنیم و سپس منتظر بمانیم تا همه آنها تمام شوند، به این ترتیب چون درخواست‌ها لازم نیست منتظر تمام شدن درخواست قبلی باشند، می‌توانند زود شروع شوند و در نتیجه زودتر حل شوند. Promise.all() یک آرایه را با وعده های حل شده پس از حل شدن همه وعده های ارسال شده به آن برمی گرداند.
در اینجا این است که چگونه ما می توانیم خود را بهبود بخشیم fetchData عملکرد با استفاده از وعده ها

الگوی اجرای همزمان

async function fetchDataConcurrently() {
  console.log("Starting to fetch data...");

  const startTime = Date.now();

  // Start both fetches concurrently
  const fastDataPromise =  fetchFastData();
  const slowDataPromise =  fetchSlowData();

  // Wait for both promises to resolve
  const [fastData, slowData] = await Promise.all([fastDataPromise, slowDataPromise]);

  const endTime = Date.now();
  const totalTime = endTime - startTime;

  console.log(`Fast data: ${fastData}`);
  console.log(`Slow data: ${slowData}`);
  console.log(`Total time taken: ${totalTime}ms`);
}
/*
expected output:
Starting to fetch data...
Fast data: Fast data
Slow data: Slow data
Total time taken: 3007ms
*/
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا یک نمودار برای تجسم بهتر است

اجرای همزمان

همه وعده‌ها را در یک آرایه به Promise.all() می‌دهیم و سپس منتظر می‌شویم. اگر چندین درخواست وجود داشته باشد، می توانیم از این طریق در زمان زیادی صرفه جویی کنیم.

با این حال یک چیز وجود دارد که باید در نظر گرفت: اگر یک وعده رد شود چه؟ اگر استفاده کنیم Promise.all() در این صورت فقط با قول مردود رد می کند. اگر بخواهیم نتیجه همه وعده ها حل شود یا رد شده چه کنیم؟
برای رسیدگی به این مورد، می توانیم استفاده کنیم Promise.allSettled(). بیایید در مورد آن نیز یاد بگیریم.

Promise.allSettled()

این یک تنوع کوچک از است Promise.all()، تفاوت این است Promise.allSettled() همیشه حل می شود، چه وعده ها به آن بگذرد، چه حل شود یا رد شود، با آرایه ای که حاوی نتایج وعده های داده شده به آن است، برمی گردد.

مثال:

const promise1 = Promise.reject("failure");
const promise2 = 42;
const promise3 = new Promise((resolve) => {
    setTimeout(resolve, 100, 'foo');
});
Promise.allSettled([promise1, promise2, promise3]).then((results) => {
    console.log(results);
});
// expected output: Array [
//   { status: "rejected", reason: "failure" },
//   { status: "fulfilled", value: 42 },
//   { status: "fulfilled", value: 'foo' }
// ]
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یکی دیگر از روش های استاتیک مفید است Promise.race()، می توان از آن برای اجرای وقفه های زمانی برای توابع ناهمگام استفاده کرد. بیایید ببینیم چگونه:

Promise.race()

متد Promise.race () قولی را برمی‌گرداند که به محض اینکه هر یک از وعده‌هایی که در یک آرایه به آن داده شده، اجرا یا رد شود، محقق یا رد می‌شود، با مقدار یا دلیلی برای رد قول.

مثال

const promise1 = new Promise((resolve,reject)=>{
     setTimeout(resolve,500,'one');
})
const promise2 = new Promise((resolve,reject)=>{
     setTimeout(resolve,100,'two');
})
Promise.race([promise1,promise2]).then((value)=>{
     console.log(value);
     // Both resolves but promise2 is faster.
})
// expected output: 'two'
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بیایید ببینیم چگونه می‌توانیم از آن برای اجرای بازه‌های زمانی استفاده کنیم:

function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Fast data");
    }, 6000);
  });
}

const fetchDataPromise = fetchData();
function fetchDataWithTimeout(promise,duration){
    return Promise.race(
         [
            promise,
            new Promise((_,reject)=>{
               setTimeout(reject,duration,"Too late.")
            })
         ]
    )
}

fetchDataWithTimeout(fetchDataPromise,5000).then((result)=>{
  console.log(result)
}).catch((error)=>{
  console.log(error)
})
/*
expected result:
Too late
*/
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این برای این پست وبلاگ بود. اگر می‌خواهید درمورد وعده‌های همگام‌سازی بیشتر بخوانید، پست وبلاگ دیگر من در مورد وعده‌های همگام‌سازی را بررسی کنید: جاوا اسکریپت ناهمزمان: نسخه TL;DR که همیشه به یاد خواهید آورد.

ممنون که خواندید و امیدوارم چیز جدیدی یاد گرفته باشید!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا