روش های بهتر برای استفاده از توابع 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 که همیشه به یاد خواهید آورد.
ممنون که خواندید و امیدوارم چیز جدیدی یاد گرفته باشید!