কীভাবে অনেক প্রতিশ্রুতি ফিরবেন এবং অন্যান্য জিনিসগুলি করার আগে সেগুলির জন্য অপেক্ষা করুন


91

আমার কাছে একটি লুপ রয়েছে যা এমন পদ্ধতিতে কল করে যা অবিচ্ছিন্নভাবে স্টাফ করে। এই লুপটি পদ্ধতিটিকে বহুবার কল করতে পারে। এই লুপের পরে, আমার আরেকটি লুপ রয়েছে যা কেবলমাত্র সমস্ত অ্যাসিনক্রোনাস স্টাফ হয়ে গেলে সম্পাদন করা দরকার।

সুতরাং এটি আমি যা চাই তা চিত্রিত করে:

for (i = 0; i < 5; i++) {
    doSomeAsyncStuff();    
}

for (i = 0; i < 5; i++) {
    doSomeStuffOnlyWhenTheAsyncStuffIsFinish();    
}

আমি প্রতিশ্রুতিগুলির সাথে খুব বেশি পরিচিত নই, তাই কেউ কি এই অর্জনে আমাকে সহায়তা করতে পারে?

আমার doSomeAsyncStuff()আচরণ এইভাবে :

function doSomeAsyncStuff() {
    var editor = generateCKEditor();
    editor.on('instanceReady', function(evt) {
        doSomeStuff();
        // There should be the resolve() of the promises I think.
    })
}

হয়তো আমাকে এরকম কিছু করতে হবে:

function doSomeAsyncStuff() {
    var editor = generateCKEditor();
    return new Promise(function(resolve,refuse) {
        editor.on('instanceReady', function(evt) {
            doSomeStuff();
            resolve(true);
        });
    });
}

তবে আমি সিনট্যাক্স সম্পর্কে নিশ্চিত নই।


আপনি কি অ্যাসিক্রোনাস কলগুলির নিয়ন্ত্রণে আছেন? তারা কি ইতিমধ্যে প্রতিশ্রুতি ফিরিয়ে দিয়েছে, বা আপনি তাদের প্রতিশ্রুতি ফিরিয়ে দিতে পারেন?
টিজে ক্রাউডার

ক্রমটি ঠিক কী? পূর্ববর্তী সমস্ত অ্যাসিঙ্ক সমাপ্তির পরে কি আপনাকে অন্যান্য ফাংশনগুলি কল করার দরকার আছে ? বা প্রতিটি অ্যাসিঙ্ক সমাপ্ত হওয়ার পরে আপনার কেবল কোনও ফাংশন কল করার দরকার আছে?
সোসডোক

আপাতত প্রথম কাজটি প্রতিশ্রুতি দেয় না। যে আমি বাস্তবায়ন করতে হবে। আমি আমার ফাংশনগুলির কর্মপ্রবাহের কিছু বিশদ যুক্ত করতে আমার বার্তাটি সম্পাদনা করতে চাই। এবং হ্যাঁ আমার দরকার দ্বিতীয় লুপে স্টাফ চালাতে শুরু করার আগে প্রথম লুপের সমস্ত জিনিস শেষ করা উচিত।
গণবিন

4
পুনরায় আপনার সম্পাদনার: "হয়তো আমি যে ভালো কিছু করতে হবে" হ্যাঁ, খুব যে ভালো, সেখানে ছাড়া sশেষে Promise
টিজে ক্রাউডার

উত্তর:


169

আপনি এটির জন্য Promise.all( স্পেক , এমডিএন ) ব্যবহার করতে পারেন : এটি ব্যক্তিগত প্রতিশ্রুতিগুলির একগুচ্ছ গ্রহণ করে এবং আপনাকে দেওয়া একক প্রতিশ্রুতি ফিরিয়ে দেয় যা আপনি যখন দিয়েছিলেন তার সমস্তগুলি সমাধান করা হয়, বা যখন তাদের কোনওটি প্রত্যাখ্যান করা হয় তখন তা প্রত্যাখ্যান করা হয়।

সুতরাং যদি আপনি doSomeAsyncStuffকোনও প্রতিশ্রুতি ফিরিয়ে দেন তবে:

    const promises = [];
//  ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− use `const` or `let`, not `var`
    
    for (let i = 0; i < 5; i++) {
//       ^^^−−−−−−−−−−−−−−−−−−−−−−−− added missing declaration
        promises.push(doSomeAsyncStuff());
    }
    
    Promise.all(promises)
        .then(() => {
            for (let i = 0; i < 5; i++) {
//               ^^^−−−−−−−−−−−−−−−− added missing declaration
                doSomeStuffOnlyWhenTheAsyncStuffIsFinish();    
            }
        })
        .catch((e) => {
            // handle errors here
        });

এমডিএন এখানে প্রতিশ্রুতি সম্পর্কিত একটি নিবন্ধ আছে । আমি আমার বই জাভাস্ক্রিপ্ট: অধ্যায় 8 এর নতুন অধ্যায়টিতে প্রতিশ্রুতিগুলির বিস্তারিত কভার করেছি : আপনি আগ্রহী হলে আমার প্রোফাইলের লিঙ্কগুলি।

এখানে একটি উদাহরণ:

 function doSomethingAsync(value) {
     return new Promise((resolve) => {
         setTimeout(() => {
             console.log("Resolving " + value);
             resolve(value);
         }, Math.floor(Math.random() * 1000));
     });
   }
   
   function test() {
       const promises = [];
       
       for (let i = 0; i < 5; ++i) {
           promises.push(doSomethingAsync(i));
       }
       
       Promise.all(promises)
           .then((results) => {
               console.log("All done", results);
           })
           .catch((e) => {
               // Handle errors here
           });
   }
   
   test();

নমুনা আউটপুট (কারণ, Math.randomপ্রথমে যা শেষ হয় তা পরিবর্তিত হতে পারে):

সমাধান 3
সমাধান 2
সমাধান 1
সমাধান 4
সমাধান 0
সমস্ত সম্পন্ন হয়েছে [0,1,2,3,4]

ঠিক আছে ধন্যবাদ আমি এখনই এটি চেষ্টা করি এবং কয়েক মিনিটের মধ্যে আমি প্রতিক্রিয়া নিয়ে আসি।
গণবিন

12
বাহ, অনেক অনেক ধন্যবাদ, এখন আমি আরও অনেক প্রতিশ্রুতি বুঝতে পারি promises এখন আমি এটি আরও ভাল পেয়েছি এবং আমি দুর্দান্ত জিনিসগুলি লিখতে শুরু করতে পারি, আপনাকে ধন্যবাদ।
গ্যানবিন

4
এছাড়াও, আপনি সম্পূর্ণ করতে এই কাজগুলো (যেমন উপহাস উন্নতি জন্য) কোন কারণে যাতে পেতে চান, তাহলে আপনি পরিবর্তন করতে পারেন Math.floor(Math.random() * 1000)থেকে(i * 1000)
ঠিক আছে নিশ্চিত

@ টিজে এখন এখন আমি কীভাবে ফলাফলের তথ্য উপস্থাপন করতে পারি এবং সেখানে ডেটা দেখানোর জন্য আমি লুপটি করতে পারি
অজিত সিং

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

6

একটি পুনরায় ব্যবহারযোগ্য ফাংশন এই প্যাটার্নটির জন্য দুর্দান্তভাবে কাজ করে:

function awaitAll(count, asyncFn) {
  const promises = [];

  for (i = 0; i < count; ++i) {
    promises.push(asyncFn());
  }

  return Promise.all(promises);
}

ওপি উদাহরণ:

awaitAll(5, doSomeAsyncStuff)
  .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
  .catch(e => console.error(e));

সম্পর্কিত প্যাটার্নটি একটি অ্যারের উপরে পুনরাবৃত্তি করছে এবং প্রতিটি আইটেমের উপর একটি এসিএনসি অপারেশন করছে:

function awaitAll(list, asyncFn) {
  const promises = [];

  list.forEach(x => {
    promises.push(asyncFn(x));
  });

  return Promise.all(promises);
}

উদাহরণ:

const books = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }];

function doSomeAsyncStuffWith(book) {
  return Promise.resolve(book.name);
}

awaitAll(books, doSomeAsyncStuffWith)
  .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
  .catch(e => console.error(e));

4
এটি কোডকে বোঝা ও পরিষ্কার করা সহজ করে তোলে। আমি মনে করি না বর্তমান উদাহরণটি (যা স্পষ্টতই ওপির কোডের সাথে মানিয়ে নেওয়া হয়েছিল) এই ন্যায়বিচার করে। এটি একটি ঝরঝরে কৌশল, ধন্যবাদ!
শান ভার্মাক

2
const doSomeAsyncStuff = async (funcs) => {
  const allPromises = funcs.map(func => func());
  return await Promise.all(allPromises);
}

doSomeAsyncStuff([
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
]);

2

এখানে বর্ণিত উত্তরগুলি বোঝার জন্য আমি এখানে কোড লিখেছি। লুপের জন্য আমার কাছে মঙ্গুজের প্রশ্ন রয়েছে, সুতরাং আমি asyncFunctionএটির জায়গাটি এখানে রাখলাম । আশা করি এটি যে কাউকে সাহায্য করবে। আপনি এই স্ক্রিপ্টটি নোডে বা জাভাস্ক্রিপ্টের যে কোনও রানটাইমটিতে চালাতে পারেন।

let asyncFunction = function(value, callback)
{
        setTimeout(function(){console.log(value); callback();}, 1000);
}



// a sample function run without promises

asyncFunction(10,
    function()
    {
        console.log("I'm back 10");
    }
);


//here we use promises

let promisesArray = [];

let p = new Promise(function(resolve)
{
    asyncFunction(20,
        function()
        {
            console.log("I'm back 20");
            resolve(20);
        }
    );
});

promisesArray.push(p);


for(let i = 30; i < 80; i += 10)
{
    let p = new Promise(function(resolve)
    {
        asyncFunction(i,
            function()
            {
                console.log("I'm back " + i);
                resolve(i);
            }
        );
    });
    promisesArray.push(p);
}


// We use Promise.all to execute code after all promises are done.

Promise.all(promisesArray).then(
    function()
    {
        console.log("all promises resolved!");
    }
)

1

/*** Worst way ***/
for(i=0;i<10000;i++){
  let data = await axios.get(
    "https://yourwebsite.com/get_my_data/"
  )
  //do the statements and operations
  //that are dependant on data
}

//Your final statements and operations
//That will be performed when the loop ends

//=> this approach will perform very slow as all the api call
// will happen in series


/*** One of the Best way ***/

const yourAsyncFunction = async (anyParams) => {
  let data = await axios.get(
    "https://yourwebsite.com/get_my_data/"
  )
  //all you statements and operations here
  //that are dependant on data
}
var promises = []
for(i=0;i<10000;i++){
  promises.push(yourAsyncFunction(i))
}
await Promise.all(promises)
//Your final statement / operations
//that will run once the loop ends

//=> this approach will perform very fast as all the api call
// will happen in parallal

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.