JavaScript Promises ও Async/Await কীভাবে কাজ করে
JavaScript Promises এমন ফলাফলকে প্রকাশ করে, যা ভবিষ্যতে পাওয়া যেতে পারে। async ও await Promise-কে সরিয়ে দেয় না; এগুলো Promise তৈরি ও ব্যবহার করার পরিষ্কার syntax দেয়। একটি async function সব সময় Promise return করে, আর await কোনো value প্রস্তুত হওয়া পর্যন্ত শুধু সেই function-টির execution থামিয়ে রাখে। এটি JavaScript thread-কে block করে না।
এই সংক্ষিপ্ত উত্তরটি সঠিক, কিন্তু সম্পূর্ণ নয়। Promise settle হলে আসলে কী বদলায়? Promise আগে থেকেই fulfilled হলেও .then() handler পরে চলে কেন? await-এর পরের code কোথায় থাকে? দেখতে কাছাকাছি দুটি async code-এর performance এত আলাদা হতে পারে কেন?
এই লেখায় আমরা syntax মুখস্থ না করে JavaScript-এর আসল behavior বোঝার মতো একটি mental model তৈরি করব।
Promise বোঝার জন্য runtime scheduling সম্পর্কে প্রাথমিক ধারণা দরকার। Task, microtask ও call stack নতুন মনে হলে আগে JavaScript Event Loop: Call Stack, Microtask, Macrotask এবং মাঝখানের সবকিছু পড়ুন। সেই লেখাটি যেখানে শেষ হয়েছে, আমরা সেখান থেকেই শুরু করছি—Promise reaction কীভাবে microtask queue-তে যায়।
Promise কোন সমস্যার সমাধান করে?
একটি সাধারণ function সঙ্গে সঙ্গে value return করতে পারে:
function getUserName() {
return "Maya";
}
const name = getUserName();
console.log(name);কিন্তু network request সাধারণত তা পারে না। Result আসতে ৩০ millisecond, তিন second বা তারও বেশি সময় লাগতে পারে। Request ব্যর্থও হতে পারে। Function call-এর মুহূর্তে final value-টি নেই বলে সেটি সঙ্গে সঙ্গে return করা সম্ভব নয়।
পুরোনো asynchronous API-তে callback ব্যবহার করা হতো:
readUser(42, (error, user) => {
if (error) {
handleError(error);
return;
}
readOrders(user.id, (error, orders) => {
if (error) {
handleError(error);
return;
}
showOrders(orders);
});
});Callback নিজে ভুল নয়। সমস্যা বাড়ে যখন অনেক dependent operation সঠিক sequence-এ চালাতে হয়, error এক ধাপ থেকে অন্য ধাপে পাঠাতে হয় এবং একাধিক কাজ একত্রে পরিচালনা করতে হয়। প্রতিটি nested level-এ control flow ও error handling আবার লিখতে হয়।
Promise interface-টি বদলে দেয়। পরবর্তী কাজকে callback হিসেবে নেওয়ার বদলে asynchronous function সঙ্গে সঙ্গে একটি object return করে:
const userPromise = readUser(42);এই object-টি user নয়। এটি ভবিষ্যৎ outcome-এর একটি stable handle। অন্য code এতে success বা failure handler যুক্ত করতে পারে, Promise-টি return করতে পারে, অন্য Promise-এর সঙ্গে combine করতে পারে, অথবা await দিয়ে এর result-এর জন্য অপেক্ষা করতে পারে।
JavaScript Promise কী?
JavaScript Promise হলো এমন একটি object, যা কোনো operation-এর eventual outcome প্রকাশ করে। Promise-এর তিনটি state আছে:
| State | অর্থ |
|---|---|
pending |
Operation এখনো কোনো outcome দেয়নি |
fulfilled |
Operation সফলভাবে একটি value দিয়েছে |
rejected |
Operation একটি rejection reason দিয়ে ব্যর্থ হয়েছে |
Fulfilled বা rejected Promise-কে settled বলা হয়। Settle হওয়ার পর Promise-এর state ও outcome আর বদলানো যায় না।
const promise = new Promise((resolve, reject) => {
const succeeded = true;
if (succeeded) {
resolve({ id: 42, name: "Maya" });
} else {
reject(new Error("Could not load the user"));
}
});resolve(value) call করলে Promise-টিকে সেই value দিয়ে resolve করার চেষ্টা হয়। reject(reason) Promise-টিকে reject করে। Promise resolved বা rejected হয়ে গেলে পরের call আর কোনো পরিবর্তন করতে পারে না।
Resolved আর fulfilled সব সময় এক নয়
শুরুর ব্যাখ্যায় “resolved” ও “fulfilled” প্রায়ই একই অর্থে ব্যবহার করা হয়। কিন্তু JavaScript-এর model আরও নির্দিষ্ট। একটি Promise অন্য একটি pending Promise-এর সঙ্গে resolve হতে পারে:
let finishRequest;
const request = new Promise((resolve) => {
finishRequest = resolve;
});
const wrapper = new Promise((resolve) => {
resolve(request);
});এখন wrapper, request-এর outcome-এর সঙ্গে locked। wrapper resolved হলেও request settle না হওয়া পর্যন্ত pending থাকবে। request fulfill হলে একই value দিয়ে wrapper fulfill হবে; reject হলে একই reason দিয়ে wrapper reject হবে।
এই adoption behavior-এর কারণেই .then() handler থেকে Promise return করলে chain flat থাকে। Nested Promise আলাদাভাবে unpack করতে হয় না।
Promise executor synchronousভাবে চলে
new Promise()-এ দেওয়া function-কে executor বলা হয়। Promise তৈরি করার সময় JavaScript এটিকে সঙ্গে সঙ্গে call করে।
console.log("A");
const promise = new Promise((resolve) => {
console.log("B: executor");
resolve("done");
});
promise.then((value) => {
console.log("D:", value);
});
console.log("C");Output হবে:
A
B: executor
C
D: doneExecutor synchronous বলে B সঙ্গে সঙ্গে দেখা যায়। কিন্তু .then() একটি Promise reaction register করে বলে D পরে আসে। Promise ইতিমধ্যে fulfilled হলেও JavaScript reaction-টিকে Job হিসেবে schedule করে; browser ও Node.js runtime Promise reaction Job-কে microtask mechanism-এর মাধ্যমে process করে।
এখান থেকে একটি গুরুত্বপূর্ণ নিশ্চয়তা পাওয়া যায়: .then(), .catch() বা .finally() callback বর্তমানে call stack-এ চলতে থাকা JavaScript-কে মাঝপথে থামায় না।
Promise কাজকে নিজে থেকে asynchronous করে না
CPU-heavy কাজ Promise-এর মধ্যে রাখলেই সেটি অন্য thread-এ চলে যায় না:
const result = new Promise((resolve) => {
const value = performExpensiveCalculation();
resolve(value);
});Calculation-টি executor-এর ভেতরে synchronousভাবেই চলবে এবং main thread block করতে পারে। Promise eventual outcome সমন্বয় করে; parallel computation দেয় না। Browser-এ CPU-intensive কাজের জন্য সাধারণত Web Worker লাগে। Node.js-এ worker thread বা আলাদা process ব্যবহার করা যেতে পারে।
Promise chaining আসলে কীভাবে কাজ করে?
.then() call করলে দুটি গুরুত্বপূর্ণ ঘটনা ঘটে:
- বর্তমান Promise-এর outcome-এর জন্য handler register হয়।
- সঙ্গে সঙ্গে একটি নতুন Promise return হয়।
const first = Promise.resolve(2);
const second = first.then((value) => value * 3);
const third = second.then((value) => value + 1);
third.then(console.log); // 7Handler কী return বা throw করছে, তার ওপর নতুন Promise-এর outcome নির্ভর করে:
| Handler-এর ফলাফল | নতুন Promise-এর outcome |
|---|---|
| সাধারণ value return করে | সেই value দিয়ে fulfill হয় |
| আরেকটি Promise/thenable return করে | তার eventual outcome গ্রহণ করে |
| Error throw করে | সেই error দিয়ে reject হয় |
| কিছু return করে না | undefined দিয়ে fulfill হয় |
শেষের নিয়মটি খুব সাধারণ bug তৈরি করে:
getUser()
.then((user) => {
getOrders(user.id); // return নেই
})
.then((orders) => {
console.log(orders); // undefined
});প্রথম handler কিছু return করেনি। তাই পরের Promise undefined দিয়ে fulfill হয়। Order request শুরু হলেও chain আর তার জন্য অপেক্ষা করে না এবং তার rejection-ও গ্রহণ করতে পারে না।
Dependent Promise-টি return করতে হবে:
getUser()
.then((user) => getOrders(user.id))
.then((orders) => showOrders(orders));এখন getOrders()-এর Promise chain-এর অংশ হওয়ায় দ্বিতীয় handler সঠিক result-এর জন্য অপেক্ষা করবে।
Error কীভাবে Promise chain দিয়ে যায়?
Promise handler-এর ভেতরে throw করা error, সেই handler থেকে return হওয়া Promise-এর rejection হয়ে যায়:
loadProfile()
.then((profile) => {
if (!profile.email) {
throw new Error("Profile has no email address");
}
return profile.email;
})
.then(sendWelcomeEmail)
.catch((error) => {
console.error("Welcome flow failed:", error);
});প্রথম handler error throw করলে JavaScript পরের fulfillment handler skip করে chain-এর নিচে rejection handler খোঁজে। এটি synchronous exception propagation-এর মতো, তবে একটানা call stack-এর বদলে Promise link দিয়ে চলে।
catch(onRejected) মূলত .then(undefined, onRejected)-এর পরিষ্কার রূপ। এটিও নতুন Promise return করে। Catch handler স্বাভাবিকভাবে return করলে chain failure থেকে recover করে fulfilled হয়ে যায়:
loadPreferences()
.catch(() => ({ theme: "system" }))
.then(applyPreferences);এটি intentional fallback হতে পারে। তবে catch handler শুধু error log করে undefined দিয়ে execution চালিয়ে দিলে বাস্তব failure লুকিয়ে যেতে পারে।
finally() কী করে?
Fulfillment বা rejection—দুই ক্ষেত্রেই যে cleanup দরকার, তার জন্য .finally() ব্যবহার করুন:
showSpinner();
loadDashboard().then(renderDashboard).catch(showError).finally(hideSpinner);finally() সাধারণত chain দিয়ে যাওয়া value বা error বদলায় না। কিন্তু এর callback error throw করলে বা rejected Promise return করলে সেই নতুন failure chain-এর outcome হয়ে যায়।
Async function আসলে কী return করে?
একটি async function যতবার call হয়, ততবার একটি নতুন Promise return করে।
async function getAnswer() {
return 42;
}
const result = getAnswer();
console.log(result instanceof Promise); // true
result.then(console.log); // 42return 42 থাকার কারণে getAnswer() সরাসরি number return করে না। এটি function-এর Promise-কে 42 দিয়ে fulfill করে।
Uncaught throw সেই Promise-কে reject করে:
async function getAnswer() {
throw new Error("No answer available");
}
getAnswer().catch(console.error);Async function অন্য Promise return করলে তার নিজের Promise returned Promise-এর outcome গ্রহণ করে।
এই নিয়মগুলোর কারণেই async function আগে থেকে থাকা Promise API-এর সঙ্গে সহজে কাজ করে। Caller .then() ব্যবহার করতে পারে, result return করতে পারে অথবা await করতে পারে। Called function-কে caller-এর style জানতে হয় না।
await-এ JavaScript কী করে?
এই function-টি দেখুন:
async function loadUser() {
console.log("before await");
const user = await fetchUser();
console.log("after await");
return user;
}loadUser() call হলে JavaScript function body synchronousভাবে চালায়, যতক্ষণ না await আসে।
সহজ কিন্তু কার্যকর mental model অনুযায়ী এরপর JavaScript নিচের কাজগুলো করে:
- Awaited expression-কে Promise-like outcome-এ convert করে।
- কোথা থেকে resume করতে হবে, সেই অবস্থাসহ বর্তমান async function suspend করে।
- Async function-এর pending Promise দিয়ে caller-এর কাছে control ফিরিয়ে দেয়।
- Awaited Promise settle হলে function চালিয়ে নেওয়ার reaction schedule করে।
- পরের একটি microtask-এ value অথবা thrown rejection দিয়ে function resume করে।
Runtime thread freeze করে না। Function-টি suspended থাকা অবস্থায় অন্য JavaScript চলতে পারে।
console.log("A");
async function demo() {
console.log("B");
await Promise.resolve();
console.log("D");
}
demo();
console.log("C");Output:
A
B
C
Ddemo() synchronousভাবে শুরু হয়ে B print করে। Promise.resolve() আগে থেকেই fulfilled হলেও await control ছেড়ে দেয়। D print করার continuation পরে microtask হিসেবে queue হয়, তাই caller আগে C print করে।
এই scheduling boundary আরও গভীরভাবে বুঝতে Event Loop লেখার Promise microtask অংশটি আবার দেখুন।
Rejection await করলে throw-এর মতো আচরণ করে
Awaited Promise reject হলে await সেই location-এ rejection reason throw করে:
async function loadAccount() {
try {
const account = await fetchAccount();
return account;
} catch (error) {
console.error("Could not load account", error);
throw error;
}
}তাই awaited Promise boundary-এর চারপাশে সাধারণ try, catch ও finally syntax কাজ করে। Outer async function তখনো Promise return করে। Error আবার throw করলে সেই Promise reject হয়, ফলে caller পরবর্তী সিদ্ধান্ত নিতে পারে।
Async/await ও .then() একই machinery ব্যবহার করে
নিচের দুটি function প্রায় একই sequence প্রকাশ করে:
function loadProfileWithThen() {
return getSession()
.then((session) => getProfile(session.userId))
.then((profile) => formatProfile(profile));
}
async function loadProfileWithAwait() {
const session = await getSession();
const profile = await getProfile(session.userId);
return formatProfile(profile);
}দ্বিতীয় version সাধারণত পড়তে সহজ, কারণ control flow ও error handling synchronous code-এর মতো দেখায়। কিন্তু এটি আলাদা asynchronous system নয়। async ও await Promise semantics-এর ওপর তৈরি।
যে style ownership ও sequencing পরিষ্কার করে, সেটি ব্যবহার করুন। ছোট transformation-এর জন্য Promise chain সুন্দর হতে পারে। Condition, loop, try...catch অথবা একাধিক named intermediate value থাকলে async/await সাধারণত সহজে বোঝা যায়।
Sequential execution বনাম concurrency
Async/await-এর ব্যয়বহুল ভুলগুলোর একটি হলো independent কাজকে অপ্রয়োজনীয়ভাবে একটির পর একটি চালানো:
const user = await fetchUser();
const settings = await fetchSettings();
const notifications = await fetchNotifications();প্রতিটি call আগের result-এর ওপর নির্ভর করলে এটি সঠিক। কিন্তু call তিনটি independent হলে অপ্রয়োজনীয় waterfall তৈরি হয়। প্রথমটি শেষ না হওয়া পর্যন্ত দ্বিতীয় request শুরু হয় না; দ্বিতীয়টি শেষ না হওয়া পর্যন্ত তৃতীয়টি অপেক্ষা করে।
Independent operation একসঙ্গে শুরু করে combined outcome await করুন:
const [user, settings, notifications] = await Promise.all([
fetchUser(),
fetchSettings(),
fetchNotifications(),
]);Promise.all() নিজে code-কে parallel করে না। Array তৈরি হওয়ার সময় তিনটি function call operation শুরু করে। সব input fulfill হলে Promise.all() ordered value-সহ একটি fulfilled Promise দেয়; কোনো input reject হলে প্রথম দেখা rejection দিয়ে returned Promise reject করে।
কোন Promise combinator কখন ব্যবহার করবেন?
| Method | কখন ব্যবহার করবেন | Outcome |
|---|---|---|
Promise.all() |
প্রতিটি result দরকার | Ordered value দিয়ে fulfill; প্রথম rejection-এ reject |
Promise.allSettled() |
প্রতিটি operation-এর outcome দেখতে হবে | সব settle হলে status object দিয়ে fulfill |
Promise.any() |
প্রথম successful result যথেষ্ট | প্রথম success-এ fulfill; সব reject হলে reject |
Promise.race() |
সবার আগে settled outcome-টি দরকার | প্রথম fulfillment বা rejection গ্রহণ করে |
Combinator settle হওয়ার পরও underlying operation চলতে পারে। Promise input operation cancel করে না। Cancellation-এর জন্য কাজটি যে API করছে, তার cooperation দরকার।
Promise মানেই cancellation নয়
Promise একটি eventual outcome প্রকাশ করে; universal stop button দেয় না। Web request cancel করতে AbortController ব্যবহার করে তার signal fetch-এ দিন:
async function loadSearchResults(query, signal) {
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
signal,
});
if (!response.ok) {
throw new Error(`Search failed with status ${response.status}`);
}
return response.json();
}
const controller = new AbortController();
const request = loadSearchResults("promises", controller.signal);
controller.abort();
request.catch((error) => {
if (error.name !== "AbortError") {
console.error(error);
}
});fetch signal বোঝে বলে abort কাজ করে। নিজের API-তে signal pass করলেই cancellation হবে না; API-টিকে signal শুনে কাজ থামাতে হবে।
JavaScript Promise ব্যবহারের সাধারণ ভুল
১. Promise return বা await করতে ভুলে যাওয়া
async function saveProfile(profile) {
writeProfile(profile); // Write শেষ হওয়ার আগেই caller শেষ হতে পারে
}Caller-এর শুধু outcome দরকার হলে return writeProfile(profile) ব্যবহার করুন। এই function-এর পরে আরও কাজ থাকলে বা এখানেই error handle করতে হলে await writeProfile(profile) লিখুন।
২. forEach-এ async callback ব্যবহার করা
forEach তার callback থেকে return হওয়া Promise-এর জন্য অপেক্ষা করে না:
users.forEach(async (user) => {
await sendEmail(user);
});
console.log("Finished"); // Email শেষ হওয়ার আগেই চলতে পারেConcurrent কাজের জন্য value-গুলোকে Promise-এ map করে combine করুন:
await Promise.all(users.map((user) => sendEmail(user)));ইচ্ছাকৃত sequential কাজের জন্য await support করা loop ব্যবহার করুন:
for (const user of users) {
await sendEmail(user);
}৩. Async Promise executor ব্যবহার করা
এই pattern এড়িয়ে চলুন:
new Promise(async (resolve, reject) => {
const value = await loadValue();
resolve(value);
});Promise constructor synchronous executor আশা করে। Executor-এর প্রথম await-এর পর throw হওয়া exception executor-এর implicit Promise-এর অংশ; সেটি outer Promise-এর সঙ্গে automaticভাবে যুক্ত নয়। সাধারণত loadValue() সরাসরি return করুন অথবা একটি async function লিখুন।
new Promise() মূলত সত্যিকারের callback-based API adapt করার সময় দরকার:
function delay(milliseconds) {
return new Promise((resolve) => {
setTimeout(resolve, milliseconds);
});
}৪. Error খুব আগে catch করা
async function loadUser() {
try {
return await requestUser();
} catch (error) {
console.error(error);
}
}Failure-এর পর function-টি undefined দিয়ে fulfill করবে। এটি বাস্তব fallback না হলে error rethrow করুন অথবা এমন layer পর্যন্ত propagate হতে দিন, যেখানে recovery, retry বা সঠিক user message দেওয়া সম্ভব।
৫. প্রতিটি HTTP error-এ fetch reject করে ভাবা
Aborted request বা network failure-এর মতো ক্ষেত্রে fetch reject করে। কিন্তু HTTP 404 বা 500-ও একটি Response দেয়। তাই response.ok অথবা response.status check করে প্রয়োজন হলে application-level error throw করুন।
৬. Unhandled rejection তৈরি করা
Promise return, await বা rejection handler যুক্ত না করে শুরু করলে failure কারও নজরে না-ও আসতে পারে:
async function onSubmit() {
saveForm(); // Floating Promise
}Ownership স্পষ্ট করুন:
async function onSubmit() {
await saveForm();
}কাজটি ইচ্ছাকৃতভাবে detached হলে যেখানে launch হচ্ছে, সেখানেই error handling যুক্ত করুন এবং caller কেন অপেক্ষা করবে না তা document করুন।
Production-ready async function-এর pattern
একটি নির্ভরযোগ্য async function-এ success, HTTP failure, parse failure, cancellation ও cleanup স্পষ্ট থাকে:
async function getArticle(slug, signal) {
const response = await fetch(`/api/articles/${encodeURIComponent(slug)}`, {
signal,
headers: {
Accept: "application/json",
},
});
if (!response.ok) {
throw new Error(`Article request failed: ${response.status}`);
}
return response.json();
}
async function renderArticle(slug, signal) {
showLoadingState();
try {
const article = await getArticle(slug, signal);
showArticle(article);
} catch (error) {
if (error.name === "AbortError") {
return;
}
showArticleError(error);
throw error;
} finally {
hideLoadingState();
}
}এখানে responsibility আলাদা। getArticle unsuccessful HTTP response-কে rejected Promise-এ রূপান্তর করে। renderArticle user-interface state পরিচালনা করে এবং intentional cancellation-কে real failure থেকে আলাদা রাখে। Error rethrow করায় monitoring বা higher boundary সেটি দেখতে পারে।
ব্যবহারিক decision guide
Asynchronous JavaScript লেখার সময় এই প্রশ্নগুলো করুন:
- এই Promise-এর owner কে? Return, await অথবা launch-এর সময় deliberateভাবে failure handle করুন।
- Operation-টি কি আগের result-এর ওপর নির্ভর করে? না করলে await করার আগে independent কাজ শুরু করুন।
- এই layer-এ failure-এর অর্থ কী? Meaningful fallback থাকলেই recover করুন।
- Operation cancel করা দরকার কি? সব cooperating layer দিয়ে cancellation signal পাঠান।
- সব result সফল হতে হবে কি? Requirement অনুযায়ী Promise combinator বেছে নিন।
- এটি কি CPU-heavy কাজ? Promise কাজটিকে বর্তমান thread থেকে সরাবে না।
পছন্দের syntax মুখস্থ করার চেয়ে এই প্রশ্নগুলো বেশি bug প্রতিরোধ করে।
প্রায় জিজ্ঞাসিত প্রশ্ন
Promise ও async/await-এর পার্থক্য কী?
Promise হলো eventual outcome প্রকাশ করা object। Async/await হলো Promise-based operation নিয়ে কাজ করার syntax। Async function Promise return করে, আর await সেই function-কে corresponding Promise settle হওয়া পর্যন্ত suspend রেখে value consume করে।
await কি JavaScript block করে?
না। await surrounding async function suspend করে, JavaScript thread নয়। Awaited result-এর ওপর নির্ভর না করা code চলতে পারে। Function-টি পরে Promise reaction-এর মাধ্যমে resume করে।
Promise synchronous নাকি asynchronous?
new Promise()-এ দেওয়া executor synchronousভাবে চলে। .then(), .catch() ও .finally()-এ register করা Promise reaction handler asynchronously চলে; runtime microtask mechanism দিয়ে Job process করে।
.then() নাকি async/await—কোনটি ব্যবহার করব?
দুটিই valid, কারণ একই Promise model ব্যবহার করে। Multi-step imperative control flow-এর জন্য async/await সাধারণত পরিষ্কার। ছোট transformation বা direct composition-এর জন্য Promise chain concise হতে পারে। Surface syntax-এর চেয়ে consistent ownership ও error handling বেশি গুরুত্বপূর্ণ।
Promise.all() কখন ব্যবহার করব?
Independent operation একসঙ্গে শুরু করা গেলে এবং প্রতিটি result দরকার হলে Promise.all() ব্যবহার করুন। Operation ভিন্ন order-এ শেষ হলেও এটি input order অনুযায়ী fulfilled value দেয় এবং কোনো input reject হলে নিজেও reject হয়।
Promise cancel করা যায় কি?
সরাসরি নয়। Promise তৈরি করা operation-কে cancellation support করতে হবে। Browser API সাধারণত AbortSignal ব্যবহার করে; custom API-তে cooperative cancellation design করতে হয়।
যে mental model মনে রাখবেন
JavaScript Promises একটি operation শুরু করা এবং তার eventual outcome observe করাকে আলাদা করে। Promise pending state থেকে settled state-এ যায় এবং handler inline call না করে reaction queue করে। প্রতিটি .then() নতুন Promise তৈরি করে। তাই returned value, returned Promise এবং thrown error chain-এর মধ্য দিয়ে যেতে পারে।
Async function এখনো Promise-producing function। এটি প্রথম await পর্যন্ত synchronousভাবে চলে, শুধু নিজেকে suspend করে এবং পরে Promise scheduling দিয়ে resume করে। Async/await control flow পড়া সহজ করে; underlying concurrency model বদলায় না।
এই নিয়মগুলো পরিষ্কার হলে asynchronous JavaScript আর বিচ্ছিন্ন কিছু special case মনে হবে না। এটি outcome, dependency, reaction ও ownership-এর একটি predictable system হয়ে উঠবে।
Full-Stack Foundations and Internals-এর অন্য লেখা দেখুন, অথবা এই guide-এর English version পড়ুন।
Standard ও source note
এই লেখার Promise state terminology, adoption rule, reaction Job এবং async function behavior official ECMAScript Promise ও AsyncFunction specification অনুসরণ করে। Promise composition ও practical usage-এর ব্যাখ্যা MDN-এর Using promises guide দিয়ে cross-check করা হয়েছে।

আলোচনা
সাইন ইন করে আলোচনায় যোগ দিন।