আমি কীভাবে শীর্ষ স্তরে async / অপেক্ষা করতে পারি?


182

আমি অনেকগুলি নিবন্ধ async/ awaitও পরে যাচ্ছি, আমি নিজে জিনিসগুলি পরীক্ষা করার সিদ্ধান্ত নিয়েছি। তবে, কেন এটি কাজ করে না তা আমার মাথা গুটিয়ে ফেলার মতো মনে হচ্ছে না:

async function main() {  
    var value = await Promise.resolve('Hey there');
    console.log('inside: ' + value);
    return value;
}

var text = main();  
console.log('outside: ' + text);

কনসোল নীচের ফলাফলগুলি দেয় (নোড v8.6.0):

> বাইরের: [বস্তু প্রতিশ্রুতি]

> ভিতরে: আরে আছে

ফাংশনের অভ্যন্তরে লগ বার্তা কেন পরে কার্যকর করা হয়? আমি ভেবেছিলাম যে কারণটি তৈরি করা হয়েছিল async/ awaitতা অ্যাসিক্রোনাস টাস্কগুলি ব্যবহার করে সিঙ্ক্রোনাস এক্সিকিউশন করার জন্য হয়েছিল।

একটি উপায় আছে আমি একটা ব্যবহার না করেই মান ফাংশন ভিতরে ফিরে ব্যবহার করতে পারে কি .then()পরে main()?


4
না, কেবলমাত্র সময় মেশিনগুলি অ্যাসিক্রোনাস কোড সিঙ্ক্রোনাস করতে পারে। awaitপ্রতিশ্রুতি thenবাক্য গঠন জন্য চিনির ছাড়া কিছুই নয় ।
বার্গি

প্রধান কেন একটি মূল্য ফেরত দেয়? এটি হওয়া উচিত, সম্ভবত এটি এন্ট্রি পয়েন্ট নয় এবং অন্য কোনও ফাংশন (যেমন অ্যাসিঙ্ক আইআইএফই) দ্বারা কল করা প্রয়োজন।
এস্তাস ফ্লাস্ক

@estus আমি নোডে জিনিসগুলি পরীক্ষা করার সময় এটি কেবলমাত্র একটি দ্রুত ফাংশনের নাম ছিল, কোনও প্রোগ্রামের প্রতিনিধি নয়main
ফিলিপ

2
FYI, async/awaitES2017 এর অংশ, ES7 (ES2016) নয়
ফেলিক্স ক্লিং

উত্তর:


267

আমার মাথাটি জড়িয়ে ধরে মনে হচ্ছে না কেন এটি কাজ করে না।

কারণ mainএকটি প্রতিশ্রুতি ফেরত; সমস্ত asyncফাংশন না।

শীর্ষ স্তরে, আপনাকে অবশ্যই:

  1. এমন একটি শীর্ষ-স্তরের asyncফাংশন ব্যবহার করুন যা কখনই প্রত্যাখ্যান করে না (যদি না আপনি "অবরুদ্ধ প্রত্যাখ্যান" ত্রুটি না চান), বা

  2. ব্যবহার করুন thenএবং catch, বা

  3. (শীঘ্রই আসছে!) শীর্ষ স্তরেরawait ব্যবহার করুন , এমন একটি প্রস্তাব যা প্রক্রিয়াতে পর্যায় 3 এ পৌঁছেছে যা awaitমডিউলটিতে শীর্ষ স্তরের ব্যবহারের অনুমতি দেয় ।

# 1 - শীর্ষ স্তরের asyncফাংশন যা কখনই প্রত্যাখ্যান করে না

(async () => {
    try {
        var text = await main();
        console.log(text);
    } catch (e) {
        // Deal with the fact the chain failed
    }
})();

লক্ষ্য করুন catch; আপনাকে অবশ্যই প্রতিশ্রুতি প্রত্যাখ্যান / অ্যাসিঙ্ক ব্যতিক্রমগুলি পরিচালনা করতে হবে , যেহেতু অন্য কিছুই হচ্ছে না; তাদের কাছে যাওয়ার জন্য আপনার কাছে কোনও কলার নেই। আপনি যদি পছন্দ করেন তবে catchফাংশনটির মাধ্যমে এটিকে কল করার পরিবর্তে ( সিনট্যাক্সের চেয়ে try/ পরিবর্তে catch) আপনি এটি করতে পারেন:

(async () => {
    var text = await main();
    console.log(text);
})().catch(e => {
    // Deal with the fact the chain failed
});

... যা কিছুটা সংক্ষিপ্ত (আমি সে কারণে এটি পছন্দ করি)।

অথবা, অবশ্যই ত্রুটিগুলি পরিচালনা করবেন না এবং কেবল "অপরিবর্তিত প্রত্যাখ্যান" ত্রুটির অনুমতি দিন।

# 2 - thenএবংcatch

main()
    .then(text => {
        console.log(text);
    })
    .catch(err => {
        // Deal with the fact the chain failed
    });

catchযদি ত্রুটি শৃঙ্খল অথবা আপনার ঘটতে হ্যান্ডলার বলা হবে thenহ্যান্ডলার। (নিশ্চিত হন যে আপনার catchহ্যান্ডলার ত্রুটিগুলি ছুঁড়ে না ফেলে, কারণ সেগুলি হ্যান্ডেল করার জন্য কিছুই নিবন্ধীকৃত নয়))

বা উভয় যুক্তি then:

main().then(
    text => {
        console.log(text);
    },
    err => {
        // Deal with the fact the chain failed
    }
);

আবার খেয়াল করুন আমরা একটি প্রত্যাখ্যান হ্যান্ডলার নিবন্ধভুক্ত করছি। তবে এই ফর্মটিতে, নিশ্চিত হয়ে নিন যে আপনার thenকলব্যাকগুলির কোনওটিই ত্রুটি ছুঁড়ে না ফেলে, এগুলি পরিচালনা করার জন্য কোনও কিছুই নিবন্ধভুক্ত নয়।

awaitএকটি মডিউলে # 3 শীর্ষ স্তরের

আপনি awaitনন-মডিউল স্ক্রিপ্টের শীর্ষ স্তরে ব্যবহার করতে পারবেন না , তবে শীর্ষ স্তরের awaitপ্রস্তাবনা ( পর্যায় 3 ) আপনাকে এটি মডিউলের শীর্ষ স্তরে ব্যবহার করতে দেয়। এটি শীর্ষ স্তরের asyncফাংশন র‌্যাপার ব্যবহারের অনুরূপ (উপরে # 1) যাতে আপনি চান না যে আপনার শীর্ষ-স্তরের কোডটি প্রত্যাখ্যান করুন (একটি ত্রুটি নিক্ষেপ করুন) কারণ এর ফলে একটি অনিচ্ছাকৃত প্রত্যাখ্যান ত্রুটি হবে। সুতরাং যদি আপনি # 1 এর মতো জিনিসগুলি ভুল হয়ে যায় তখন আপনি এই অনানন্দিত প্রত্যাখ্যান না করতে চাইলে আপনি নিজের কোডটি একটি ত্রুটি হ্যান্ডলারের মধ্যে মোড়াতে চান:

// In a module, once the top-level `await` proposal lands
try {
    var text = await main();
    console.log(text);
} catch (e) {
    // Deal with the fact the chain failed
}

মনে রাখবেন যে আপনি যদি এটি করেন তবে আপনার মডিউল থেকে আমদানি করা কোনও মডিউল আপনার প্রতিশ্রুতি awaitস্থির না হওয়া পর্যন্ত অপেক্ষা করবে ; শীর্ষ-স্তরের ব্যবহার করে মডিউলটি যখন awaitমূল্যায়ন করা হয়, এটি মূলত মডিউল লোডারকে (যেমন কোনও asyncফাংশন করে) প্রতিশ্রুতি দেয়, যা নির্ভর করে যে কোনও মডিউলগুলির উপর নির্ভর করে কোনও মডিউলগুলি মূল্যায়নের আগে সেই প্রতিশ্রুতিটি নিষ্পত্তি না হওয়া পর্যন্ত অপেক্ষা করে।


এটি একটি প্রতিশ্রুতি হিসাবে চিন্তা করা এখন ফাংশন কেন সঙ্গে সঙ্গে ফিরে আসে তা ব্যাখ্যা করে। আমি একটি শীর্ষ-স্তরের বেনামে অ্যাসিঙ্ক ফাংশন তৈরির জন্য পরীক্ষা-নিরীক্ষা করেছি এবং আমি এখন ফলস্বরূপ ফলাফল পেয়েছি
ফিলিপ

2
@ ফিলিপ: হ্যাঁ, async/ awaitপ্রতিশ্রুতিগুলির আশেপাশে সিনট্যাকটিক চিনি (ভাল ধরণের চিনি :-))। আপনি কেবল এটি প্রতিশ্রুতি ফিরিয়ে দেওয়ার কথা ভাবছেন না ; এটা আসলে করে। ( বিবরণ ।)
টিজে ক্রাউডার

1
@ লুকম্যাকগ্রিগোর - asyncপ্রথমে সমস্ত বিকল্প দিয়ে আমি উপরে উভয়ই দেখিয়েছি । শীর্ষ স্তরের ফাংশনের জন্য, আমি এটি যে কোনও উপায়ে দেখতে পাচ্ছি (বেশিরভাগ কারণ asyncসংস্করণে দুটি স্তরের ইন্ডেন্টেশন কারণে )।
টিজে ক্রাউডার

3
@ ফিলিপ - আমি এখনই উত্তরটি আপডেট করেছি যে শীর্ষ স্তরের awaitপ্রস্তাবটি পর্যায়ের ৩: :-) এ পৌঁছেছে
টিজে ক্রোডার

1
@ সুরজশ্রেষ্ঠ - না, তবে এটি এমন সমস্যা নয় যা এটি হয় না। :-)
টিজে ক্রোডার

7

শীর্ষ-স্তরটিawait পর্যায় 3 এ চলে গেছে, সুতরাং আপনার প্রশ্নের উত্তর কীভাবে আমি শীর্ষ স্তরে অ্যাসিঙ্ক ব্যবহার করতে / অপেক্ষা করতে পারি? শুধুমাত্র awaitকলটি যুক্ত করতে হবে main():

async function main() {  
    var value = await Promise.resolve('Hey there');
    console.log('inside: ' + value);
    return value;
}

var text = await main();  
console.log('outside: ' + text)

বা শুধু:

const text = await Promise.resolve('Hey there');
console.log('outside: ' + text)

মনে রাখবেন যে এটি এখনও কেবল ওয়েবপ্যাক @v5.0.0 - alpha.15 এ উপলব্ধ ।

আপনি যদি টাইপস্ক্রিপ্ট ব্যবহার করছেন তবে এটি 3.8 এ অবতরণ করেছে

v8 মডিউলগুলিতে সমর্থন যোগ করেছে ।

এটি ডেনো দ্বারা সমর্থিত (যেমন গঞ্জালো-বাহামোঞ্জেজ মন্তব্য করেছেন)।


বেশ দারুন. নোড বাস্তবায়নের জন্য আমাদের কাছে কি কোনও রোডম্যাপ রয়েছে
ফিলিপ

জানেন না তবে খুব সম্ভবত আমরা খুব শীঘ্রই একটি টাইপস্ক্রিপ্ট এবং ব্যাবেল বাস্তবায়ন দেখতে পাব। টাইপসক্রিপ্ট টিমের স্টেজ -৩ টি ভাষা বৈশিষ্ট্যগুলি প্রয়োগ করার নীতি রয়েছে এবং প্রস্তাবগুলির পরীক্ষার জন্য বাবেল প্লাগইন সাধারণত TC39 প্রক্রিয়ার অংশ হিসাবে নির্মিত হয়। দেখুন github.com/Microsoft/TypeScript/issues/...
তারো

এটি ডেনোতেও উপলব্ধ (কেবলমাত্র জেএস, টাইপসক্রিপ্ট এখনও এটি সমর্থন করে না github.com/microsoft/TypeScript/issues/25988 ) deno.land দেখুন deno.news/issues/…
গনজালো বাহামোন্দেজ

সিনট্যাক্স এরর: প্রতীক্ষাটি কেবলমাত্র অ্যাসিঙ্ক ফাংশনেই বৈধ
সুদীপ্ত ধারা

4

এই সমস্যার আসল সমাধান হ'ল এটি আলাদাভাবে যোগাযোগ করা।

সম্ভবত আপনার লক্ষ্যটি এক প্রকারের সূচনা যা সাধারণত কোনও অ্যাপ্লিকেশন শীর্ষ স্তরে ঘটে।

সমাধানটি হ'ল এটি নিশ্চিত করা যে আপনার আবেদনের শীর্ষ স্তরে কেবলমাত্র একটি একক জাভাস্ক্রিপ্ট বিবৃতি রয়েছে। আপনার অ্যাপ্লিকেশনটির শীর্ষে যদি আপনার কাছে কেবলমাত্র একটি বিবৃতি থাকে তবে আপনি অন্য যে কোনও জায়গায় অ্যাসিঙ্কটি ব্যবহার / অপেক্ষায় থাকতে পারেন (অবশ্যই স্বাভাবিক সিনট্যাক্সের বিধি অনুসারে)

অন্য কোনও উপায়ে রাখুন, আপনার পুরো শীর্ষ স্তরের একটি ফাংশনে মুড়ে রাখুন যাতে এটি শীর্ষ স্তরের আর না থাকে এবং এটি কীভাবে async চালাতে হবে / কোনও অ্যাপ্লিকেশনের শীর্ষ স্তরে অপেক্ষা করতে হবে - এই প্রশ্নটি সমাধান করে না you

আপনার অ্যাপ্লিকেশনটির শীর্ষ স্তরের দেখতে এটি দেখতে পাওয়া উচিত:

import {application} from './server'

application();

1
আপনি সঠিক যে আমার লক্ষ্য সূচনা। ডাটাবেস সংযোগ, ডেটা টান ইত্যাদির মতো বিষয়গুলি কিছু ক্ষেত্রে বাকী অ্যাপ্লিকেশনটি চালিয়ে যাওয়ার আগে ব্যবহারকারীর ডেটা নেওয়া দরকার ছিল। মূলত আপনি প্রস্তাব করছেন যে application()অ্যাসিঙ্ক হবে?
ফিলিপ

1
না, আমি কেবল বলছি যে যদি আপনার আবেদনের মূলে যদি একটি মাত্র জাভাস্ক্রিপ্ট বিবৃতি থাকে তবে আপনার সমস্যাটি চলে গেছে - শীর্ষ স্তরের বিবৃতি হিসাবে দেখানো হয়েছে অ্যাসিঙ্ক নয়। সমস্যাটি হ'ল শীর্ষ স্তরে অ্যাসিঙ্কটি ব্যবহার করা সম্ভব নয় - আপনি আসলে সেই স্তরে অপেক্ষা করার অপেক্ষায় থাকতে পারবেন না - সুতরাং শীর্ষ স্তরে যদি কেবলমাত্র একটি বিবৃতি থাকে তবে আপনি সেই সমস্যাটিকে পাশছাড়া করেছেন। আপনার ইনিশিয়ালাইজেশন অ্যাসিঙ্ক কোডটি এখন কিছু আমদানিকৃত কোডের নীচে রয়েছে এবং অতএব অ্যাসিঙ্কটি ঠিক কাজ করবে, এবং আপনি আপনার অ্যাপ্লিকেশনটির শুরুতে সমস্ত কিছু শুরু করতে পারেন।
ডিউক ডগল

1
সংশোধন - অ্যাপ্লিকেশনটি একটি অ্যাসিঙ্ক ফাংশন।
ডিউক ডগল

4
আমি পরিষ্কার হয়ে যাচ্ছি না দুঃখিত। মুল বক্তব্যটি হ'ল সাধারনত, শীর্ষ স্তরে, একটি অ্যাসিঙ্ক ফাংশন অপেক্ষা করে না .... জাভাস্ক্রিপ্ট সরাসরি পরবর্তী বিবৃতিতে চলে যায় যাতে আপনি নিশ্চিত হতে পারবেন না যে আপনার আর ডি কোডটি সম্পন্ন হয়েছে। আপনার অ্যাপ্লিকেশনটির শীর্ষে যদি কেবলমাত্র একটি একক বিবৃতি থাকে তবে এটি কোনও বিষয় নয়।
ডিউক ডগল

3

বর্তমানের উত্তরের উপরে আরও কিছু তথ্য দিতে:

node.jsএকটি ফাংশন বডি গঠনের জন্য কোনও ফাইলের বিষয়বস্তুগুলি বর্তমানে স্ট্রিং-জাতীয় উপায়ে সংক্ষিপ্ত করা হয়।

উদাহরণস্বরূপ আপনার যদি কোনও ফাইল থাকে test.js:

// Amazing test file!
console.log('Test!');

তারপরে node.jsএমন কোনও ফাংশনটি গোপনে প্রকাশ করবে:

function(require, __dirname, ... a bunch more top-level properties) {
  // Amazing test file!
  console.log('test!');
}

প্রধান বিষয় লক্ষনীয়, ফলস্বরূপ ফাংশনটি একটি অ্যাসিঙ্ক ফাংশন নয়। সুতরাং আপনি awaitসরাসরি এটির ভিতরে শব্দটি ব্যবহার করতে পারবেন না !

তবে বলুন আপনাকে এই ফাইলে প্রতিশ্রুতি নিয়ে কাজ করা দরকার, তবে দুটি সম্ভাব্য পদ্ধতি রয়েছে:

  1. ফাংশনের ভিতরে await সরাসরি ব্যবহার করবেন না
  2. ব্যবহার করবেন না await

বিকল্প 1 এর জন্য আমাদের একটি নতুন সুযোগ তৈরি করা প্রয়োজন (এবং এই সুযোগটি হতে পারে async, কারণ এটির উপর আমাদের নিয়ন্ত্রণ রয়েছে):

// Amazing test file!
// Create a new async function (a new scope) and immediately call it!
(async () => {
  await new Promise(...);
  console.log('Test!');
})();

বিকল্প 2 এর জন্য আমাদের অবজেক্ট-ভিত্তিক প্রতিশ্রুতি API ব্যবহার করতে হবে (প্রতিশ্রুতিগুলির সাথে কাজ করার জন্য কম সুন্দর তবে সমানভাবে কার্যকরী দৃষ্টান্ত)

// Amazing test file!
// Create some sort of promise...
let myPromise = new Promise(...);

// Now use the object-oriented API
myPromise.then(() => console.log('Test!'));

আমি ব্যক্তিগতভাবে আশাবাদী, যদি এটি কার্যকর হয় তবে নোড.জেএস ডিফল্টরূপে একটি asyncকার্যক্রমে কোডটি মিশ্রিত করে। এই মাথাব্যথা থেকে মুক্তি পেতে পারে।


0

শীর্ষ স্তরের প্রতীক্ষা আসন্ন ইকামাস্ক্রিপ্ট স্ট্যান্ডার্ডের একটি বৈশিষ্ট্য। বর্তমানে, আপনি এটি টাইপস্ক্রিপ্ট 3.8 দিয়ে ব্যবহার শুরু করতে পারেন (এই সময়ে আরসি সংস্করণে)।

কীভাবে টাইপস্ক্রিপ্ট ইনস্টল করবেন 3.8

নিম্নলিখিত কমান্ডটি ব্যবহার করে আপনি এনপিএম থেকে ইনস্টল করে টাইপস্ক্রিপ্ট ৩.৮ ব্যবহার শুরু করতে পারেন :

$ npm install typescript@rc

এই সময়ে, আপনাকে rcসর্বশেষতম টাইপস্ক্রিপ্ট 3.8 সংস্করণ ইনস্টল করতে ট্যাগ যুক্ত করতে হবে।


তবে আপনাকে কীভাবে এটি ব্যবহার করবেন তা ব্যাখ্যা করতে হবে?
বিপ্লবগুলি

-2

যেহেতু main()অবিচ্ছিন্নভাবে এটি চালায় এটি প্রতিশ্রুতি দেয়। then()পদ্ধতিতে আপনাকে ফলাফল পেতে হবে । এবং কারণ then()রিটার্নগুলিও প্রতিশ্রুতি দেয়, আপনাকে process.exit()প্রোগ্রামটি শেষ করতে কল করতে হবে।

main()
   .then(
      (text) => { console.log('outside: ' + text) },
      (err)  => { console.log(err) }
   )
   .then(() => { process.exit() } )

2
ভুল। একবার সমস্ত প্রতিশ্রুতি গ্রহণ বা প্রত্যাখ্যান হয়ে গেলে এবং মূল থ্রেডে আর কোনও কোড চলমান না থাকলে প্রক্রিয়াটি নিজেই শেষ হয়ে যায়।

@ দেভ: সাধারণত exit()কোনও ত্রুটি ঘটেছে কি না তা সিগন্যাল করতে আপনি বিভিন্ন মানটি পাস করতে চান ।
9000

@ 9000 হ্যাঁ, তবে এটি এখানে করা হচ্ছে না এবং যেহেতু 0 এর একটি প্রস্থান কোড ডিফল্ট তাই এটি অন্তর্ভুক্ত করার দরকার নেই

@ 9000 আসলে, ত্রুটি হ্যান্ডলারটি সম্ভবত ব্যবহার করা উচিতprocess.exit(1)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.