পতাকা পর্যন্ত সত্য অপেক্ষা করুন = সত্য


96

আমার কাছে জাভাস্ক্রিপ্ট ফাংশনটি রয়েছে:

function myFunction(number) {

    var x=number;
    ...
    ... more initializations
    //here need to wait until flag==true
    while(flag==false)
    {}

    ...
    ... do something

}

সমস্যাটি হ'ল জাভাস্ক্রিপ্টটি যখন আটকে গিয়েছিল এবং আমার প্রোগ্রামটি আটকে যায়। সুতরাং আমার প্রশ্নটি হল "ব্যস্ত-অপেক্ষা" ব্যতীত পতাকাটি সত্য না হওয়া পর্যন্ত আমি কীভাবে ফাংশনের মাঝখানে অপেক্ষা করতে পারি?


4
আপনার initializations জন্য প্রতিশ্রুতি প্যাটার্ন ব্যবহার করুন - বেশ কিছু লাইব্রেরি খুঁজে পাওয়া যেতে পারে পছন্দ jQuery.Deferred, Q, async, ...
Sirko

কোথায় এটি সঠিকভাবে ব্যবহার করবেন এবং কীভাবে?
ইলে জিদমান

4
বিভিন্ন গ্রন্থাগারের প্রতিশ্রুতি বাস্তবায়ন বর্ণনা করার জন্য প্রচুর টিউটোরিয়াল রয়েছে। jQuery.Deferred বা প্রশ্ন । বিটিডব্লিউ, আপনার অন্তর্নিহিত সমস্যাটি এই প্রশ্নের মতোই ।
সিরকো

4
2018 এ কারও পাঠের জন্য, প্রতিশ্রুতিগুলি অপেরা মিনি এবং আই 11 এর পাশাপাশি সমস্ত ব্রাউজার দ্বারা সমর্থিত।
ড্যানিয়েল রেইনা

মূল সমস্যাটি হ'ল ইভেন্ট-ডাইভেন একক থ্রেডেড জেএসে সত্যিকারের অবরুদ্ধ হওয়া (ঘুম) অপেক্ষা করা অসম্ভব। আপনি কেবল অপেক্ষা হ্যান্ডলার তৈরি করতে পারেন। আরো দেখুন: stackoverflow.com/questions/41842147/...
SalientBrain

উত্তর:


74

কারণ ব্রাউজারে জাভাস্ক্রিপ্টটি একক থ্রেডযুক্ত (ওয়েবকর্মীরা ছাড়া যা এখানে জড়িত নয়) এবং জাভাস্ক্রিপ্টের কার্যকরকরণের একটি থ্রেড অন্য চালানোর আগে সম্পূর্ণ হতে চলেছে, আপনার বক্তব্য:

while(flag==false) {}

কেবলমাত্র চিরকাল চলবে (বা ব্রাউজারটি কোনও প্রতিক্রিয়াবিহীন জাভাস্ক্রিপ্ট লুপ সম্পর্কে অভিযোগ না করা পর্যন্ত) পৃষ্ঠাটি স্তব্ধ হয়ে যাবে এবং অন্য কোনও জাভাস্ক্রিপ্ট কখনও চালানোর সুযোগ পাবে না, সুতরাং পতাকাটির মান কখনই পরিবর্তন করা যায় না।

আরও কিছুটা ব্যাখ্যার জন্য, জাভাস্ক্রিপ্ট একটি ইভেন্ট চালিত ভাষা । তার অর্থ এটি জাভাস্ক্রিপ্টের এক টুকরো চালায় যতক্ষণ না এটি দোভাষীটিতে নিয়ন্ত্রণ ফিরিয়ে দেয়। তারপরে, এটি যখন অনুবাদকের কাছে ফিরে আসে তখনই জাভাস্ক্রিপ্ট ইভেন্টের সারি থেকে পরবর্তী ইভেন্টটি পেয়ে এটি চালায়।

টাইমার এবং নেটওয়ার্ক ইভেন্টের মতো সমস্ত জিনিস ইভেন্টের সারি দিয়ে চলে। সুতরাং, যখন টাইমার গুলি চালায় বা কোনও নেটওয়ার্কের অনুরোধ উপস্থিত হয়, এটি বর্তমানে চলমান জাভাস্ক্রিপ্টটিকে কখনই "বাধা" দেয় না। পরিবর্তে, কোনও ইভেন্ট জাভাস্ক্রিপ্ট ইভেন্টের কাতারে পরে যায় এবং তারপরে, যখন বর্তমানে চলমান জাভাস্ক্রিপ্ট শেষ হয়, পরবর্তী ইভেন্টটি ইভেন্টের সারি থেকে টানা হয় এবং এটি চলার পালা পায়।

সুতরাং, যখন আপনি একটি অসীম লুপ করবেন while(flag==false) {} , বর্তমানে চলমান জাভাস্ক্রিপ্ট কখনই শেষ হয় না এবং এভাবে পরবর্তী ইভেন্টটি ইভেন্টের সারি থেকে কখনই টানা হয় না এবং এভাবে flagকখনই এর মান পরিবর্তন হয় না। তারা এখানে কী জাভাস্ক্রিপ্ট চালিত বাধা হয় না । যখন একটি টাইমার গুলি চালায়, এটি বর্তমানে চলমান জাভাস্ক্রিপ্ট বাধা দেয় না, অন্য কোনও জাভাস্ক্রিপ্ট চালান এবং তারপরে বর্তমানে চলমান জাভাস্ক্রিপ্টটি চালিয়ে যেতে দিন। এটি বর্তমানে চলমান জাভাস্ক্রিপ্টটি চালানোর পালা পাওয়ার জন্য না করা পর্যন্ত ইভেন্টের কাতারে অপেক্ষা করে।


আপনাকে যা করতে হবে তা হল আপনার কোডটি কীভাবে কাজ করে তা পুনর্বিবেচনা করা এবং flagমান পরিবর্তনের সময় আপনি যে কোডটি চালাতে চান তা ট্রিগার করার জন্য আলাদা উপায় খুঁজে বের করতে । জাভাস্ক্রিপ্ট একটি ইভেন্ট চালিত ভাষা হিসাবে ডিজাইন করা হয়েছে। সুতরাং, আপনাকে যা করার দরকার তা হ'ল কোন ইভেন্টগুলিতে আপনি আগ্রহের নিবন্ধন করতে পারবেন যাতে আপনি পতাকাটি পরিবর্তনের কারণ হতে পারে এমন ইভেন্টের জন্য শুনতে পারেন এবং আপনি সেই ইভেন্টে পতাকাটি পরীক্ষা করতে পারেন বা আপনি নিজের ইভেন্টটি ট্রিগার করতে পারেন যে কোনও কোড পতাকা পরিবর্তন করতে পারে বা আপনি একটি কলব্যাক ফাংশন প্রয়োগ করতে পারেন যে পতাকাটি যেই কোড পরিবর্তন করে তা আপনার কলব্যাক কল করতে পারে যখনই পতাকাটির মান পরিবর্তন করার জন্য দায়ী কোডের অংশটি এর মান পরিবর্তন করে true, এটি কেবল কলব্যাক ফাংশনকে কল করে এবং এইভাবে আপনার কোডটি পতাকাটি সেট হয়ে গেলে এটি চলতে চায়trueসঠিক সময়ে চালানো হবে। এটি নিয়মিত পতাকাটির মান পরীক্ষা করতে কোনও ধরণের টাইমার ব্যবহার করার চেষ্টা করার চেয়ে অনেক বেশি দক্ষ।

function codeThatMightChangeFlag(callback) {
    // do a bunch of stuff
    if (condition happens to change flag value) {
        // call the callback to notify other code
        callback();
    }
}

99

জাভাস্ক্রিপ্ট একক থ্রেডেড, অতএব পৃষ্ঠাটি ব্লক করার আচরণ। আপনি অন্যদের দ্বারা প্রস্তাবিত স্থগিত / প্রতিশ্রুতি পদ্ধতির ব্যবহার করতে পারেন, তবে সবচেয়ে প্রাথমিক উপায়টি হ'ল ব্যবহার করা window.setTimeout। যেমন

function checkFlag() {
    if(flag == false) {
       window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
    } else {
      /* do something*/
    }
}
checkFlag();

এখানে আরও ব্যাখ্যা সহ একটি ভাল টিউটোরিয়াল: টিউটোরিয়াল

সম্পাদনা

অন্যরা যেমন উল্লেখ করেছে, সেরা উপায় হ'ল কলব্যাকগুলি ব্যবহার করার জন্য আপনার কোডটি পুনরায় গঠন করা। যাইহোক, এই উত্তরটি আপনাকে একটি ধারণা দেয় যাতে আপনি কীভাবে একটি অ্যাসিক্রোনাস আচরণটি 'অনুকরণ' করতে পারেন window.setTimeout


4
একদিকে যেমন আমি এই উত্তরটি সত্যিই পছন্দ করি কারণ এটি অবশ্যই একটি জেএস 'অপেক্ষা' এটি যদি আপনি কোনও মান ফেরত চান তবে এটি এতটা ব্যবহারযোগ্য হয় না। আপনি যদি কোনও মান না ফেরান তবে আমি নিশ্চিত নই যে প্যাটার্নটির জন্য সত্যিকারের বিশ্বের ব্যবহার আছে?
মার্টিন মিজার

আপনি অবশ্যই একটি প্রতিশ্রুতি ফিরিয়ে দিতে পারেন এবং সেই পদ্ধতিতে কার্যটি বাস্তবায়ন করতে পারেন। তবে এটির জন্য সাধারণত কোনও তৃতীয় পক্ষের লাইব্রেরি প্রয়োজন যা প্রতিশ্রুতিগুলি বা পলফিল প্রয়োগ করে, যদি না আপনি ইসিএমএ-262 ব্যবহার করেন। কোনও প্রতিশ্রুতি না দিয়ে, সর্বোত্তম উপায় হ'ল কলব্যাক প্রক্রিয়াটি কলকারীর কাছে সিগন্যাল করার জন্য যে কোনও ফলাফল উপলব্ধ রয়েছে use
কিরণ

: আপনি পরামিতি পাস করতে পারেন যদি প্রয়োজন stackoverflow.com/questions/1190642/...
SharpC

4
এটি এমন দুর্দান্ত উত্তর। অনেক প্রযুক্তি ফোরামে খোঁড়াখুঁড়ি করার পরে আমি প্রায় ছেড়ে দিয়েছিলাম। আমি মনে করি এটি আমার জন্য নিখুঁতভাবে কাজ করেছে কারণ আমি কোনও মূল্য ফিরিয়ে দিচ্ছি। এটি ইন্টারনেট এক্সপ্লোরারেও কাজ করেছে a একগুচ্ছ ধন্যবাদ।
জোসেফ 20

19

প্রতিশ্রুতি , অ্যাসিঙ্ক \ অপেক্ষা এবং ইভেন্টইমিটার ব্যবহার করে সমাধান যা কোনও প্রকার লুপ ছাড়াই পতাকা পরিবর্তনে তাত্ক্ষণিক প্রতিক্রিয়া করতে দেয়

const EventEmitter = require('events');

const bus = new EventEmitter();
let lock = false;

async function lockable() {
    if (lock) await new Promise(resolve => bus.once('unlocked', resolve));
    ....
    lock = true;
    ...some logic....
    lock = false;
    bus.emit('unlocked');
}

EventEmitterনোডে অন্তর্নির্মিত ব্রাউজারে আপনাকে এটি নিজের দ্বারা অন্তর্ভুক্ত করতে হবে, উদাহরণস্বরূপ এই প্যাকেজটি ব্যবহার করে: https://www.npmjs.com/package/eventemitter3


17

ES6 Async / Await সহ,

let meaningOfLife = false;
async function waitForMeaningOfLife(){
   while (true){
        if (meaningOfLife) { console.log(42); return };
        await null; // prevents app from hanging
   }
}
waitForMeaningOfLife();
setTimeout(()=>meaningOfLife=true,420)

4
লোকেরা এটি কীভাবে মিস করেছিল
এভিড

16
function waitFor(condition, callback) {
    if(!condition()) {
        console.log('waiting');
        window.setTimeout(waitFor.bind(null, condition, callback), 100); /* this checks the flag every 100 milliseconds*/
    } else {
        console.log('done');
        callback();
    }
}

ব্যবহার:

waitFor(() => window.waitForMe, () => console.log('got you'))

11

ইকমা স্ক্রিপ্ট 2017 এর সাহায্যে আপনি async-wait ব্যবহার করতে পারেন এবং একসাথে এটি করার জন্য এবং যখন প্রোগ্রামটি ক্রাশ বা লক হবে না এমন কি ভেরিয়েবল কখনও সত্য হবে না be

//First define some delay function which is called from async function
function __delay__(timer) {
    return new Promise(resolve => {
        timer = timer || 2000;
        setTimeout(function () {
            resolve();
        }, timer);
    });
};

//Then Declare Some Variable Global or In Scope
//Depends on you
var flag = false;

//And define what ever you want with async fuction
async function some() {
    while (!flag)
        await __delay__(1000);

    //...code here because when Variable = true this function will
};


8

প্রতিশ্রুতি ব্যবহার করে আধুনিক সমাধান

myFunction() মূল প্রশ্নে নিম্নলিখিত হিসাবে পরিবর্তন করা যেতে পারে

async function myFunction(number) {

    var x=number;
    ...
    ... more initializations

    await until(_ => flag == true);

    ...
    ... do something

}

until()এই ইউটিলিটি ফাংশন কোথায়

function until(conditionFunction) {

  const poll = resolve => {
    if(conditionFunction()) resolve();
    else setTimeout(_ => poll(resolve), 400);
  }

  return new Promise(poll);
}

অ্যাসিঙ্ক / অপেক্ষার এবং তীর ফাংশনগুলির কয়েকটি উল্লেখ একই ধরণের পোস্টে রয়েছে: https://stackoverflow.com/a/52652681/209794


4

ওভার (ea .each) অবজেক্টের পুনরাবৃত্তি এবং প্রতিটি বস্তুর উপর দীর্ঘায়িত চলমান ক্রিয়াকলাপ (নেস্টেড এজাক্স সিঙ্ক কলগুলি সহ) চালানোর জন্য:

আমি প্রথমে done=falseপ্রতিটি উপর একটি কাস্টম সম্পত্তি সেট ।

তারপরে, একটি পুনরাবৃত্ত ফাংশনে প্রতিটি সেট করে done=trueব্যবহার চালিয়ে যান setTimeout। (এটি একটি অপারেশন যার অর্থ অন্য সমস্ত ইউআই বন্ধ করা, একটি অগ্রগতি বার দেখানো এবং অন্য সমস্ত ব্যবহার আটকাতে হবে যাতে আমি সিঙ্ক কলগুলির জন্য নিজেকে ক্ষমা করে দিয়েছি))

function start()
{
    GlobalProducts = getproductsfromsomewhere();
    $.each(GlobalProducts, function(index, product) {
         product["done"] = false;
    });

    DoProducts();
}
function DoProducts()
{
    var doneProducts = Enumerable.From(GlobalProducts).Where("$.done == true").ToArray(); //linqjs

    //update progress bar here

    var nextProduct = Enumerable.From(GlobalProducts).Where("$.done == false").First();

        if (nextProduct) {
            nextProduct.done = true;
            Me.UploadProduct(nextProduct.id); //does the long-running work

            setTimeout(Me.UpdateProducts, 500)
        }
}

1

লাইটবার্ডের উত্তরের অনুরূপ, আমি নিম্নলিখিত পদ্ধতিটি ব্যবহার করি

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function until(fn) {
    while (!fn()) {
        await sleep(0)
    }
}

async function myFunction(number) {
    let x = number
    ...
    ... more initialization

    await until(() => flag == true)

    ...
    ... do something
}

1

আমি @ কিরান পদ্ধতির অনুসরণের মতো ব্যবহার করার চেষ্টা করেছি:

checkFlag: function() {
  var currentObject = this; 
  if(flag == false) {
      setTimeout(currentObject.checkFlag, 100); 
   } else {
     /* do something*/
   }
}

(ফ্রেমওয়ার্ক যা আমি ব্যবহার করছি আমাকে এইভাবে ফাংশনগুলি সংজ্ঞায়িত করতে বাধ্য করে)। তবে সাফল্য ছাড়াই কারণ যখন দ্বিতীয়বার চেকফ্ল্যাজ ফাংশনের ভিতরে মৃত্যুদণ্ড আসে, thisএটি আমার উদ্দেশ্য নয় Window। সুতরাং, আমি নীচের কোড দিয়ে শেষ করেছি

checkFlag: function() {
    var worker = setInterval (function(){
         if(flag == true){             
             /* do something*/
              clearInterval (worker);
         } 
    },100);
 }

1

ইভেন্টট্যাজেট এপিআই সহ অ ব্লক করা জাভাস্ক্রিপ্ট ব্যবহার করছে

আমার উদাহরণে, কলব্যাকটি ব্যবহার করার আগে আমাকে অপেক্ষা করতে হবে। এই কলব্যাকটি কখন সেট করা হবে তা আমার কোনও ধারণা নেই। এটি সম্পাদন করা দরকার পরে এটি আগে হতে পারে। এবং আমাকে এটি বেশ কয়েকবার কল করতে হবে (সবকিছুই অ্যাসিঙ্ক)

// bus to pass event
const bus = new EventTarget();

// it's magic
const waitForCallback = new Promise((resolve, reject) => {
    bus.addEventListener("initialized", (event) => {
        resolve(event.detail);
    });
});



// LET'S TEST IT !


// launch before callback has been set
waitForCallback.then((callback) => {
    console.log(callback("world"));
});


// async init
setTimeout(() => {
    const callback = (param) => { return `hello ${param.toString()}`; }
    bus.dispatchEvent(new CustomEvent("initialized", {detail: callback}));
}, 500);


// launch after callback has been set
setTimeout(() => {
    waitForCallback.then((callback) => {
        console.log(callback("my little pony"));
    });
}, 1000);


1

delayব্যবহারের জন্য খুব সহজ একটি নোড প্যাকেজ রয়েছে

const delay = require('delay');

(async () => {
    bar();

    await delay(100);

    // Executed 100 milliseconds later
    baz();
})();

1

যদি আপনার ব্যবহারের অনুমতি দেওয়া হয়: async/awaitআপনার কোডে, আপনি এটি ব্যবহার করে দেখতে পারেন:

const waitFor = async (condFunc: () => boolean) => {
  return new Promise((resolve) => {
    if (condFunc()) {
      resolve();
    }
    else {
      setTimeout(async () => {
        await waitFor(condFunc);
        resolve();
      }, 100);
    }
  });
};

const myFunc = async () => {
  await waitFor(() => (window as any).goahead === true);
  console.log('hello world');
};

myFunc();

ডেমো এখানে: https://stackblitz.com/edit/typescript-bgtnhj?file=index.ts

কনসোলে, শুধু কপি / পেস্ট: goahead = true


1

আমি এখানে কলব্যাক সলিউশনগুলির লাইন ধরে একটি মতামত নিয়েছি, তবে এটি কিছুটা জেনেরিক করার চেষ্টা করেছি। ধারণাটি হ'ল আপনি কোনও ক্রুতে কিছু পরিবর্তন করার পরে আপনাকে যে ক্রিয়াকলাপগুলি সম্পাদন করতে হবে তা যুক্ত করুন। জিনিসটি হয়ে গেলে, আপনি তারপরে সারিটি লুপ করবেন, ফাংশনগুলিতে কল করুন এবং সারিটি খালি করুন।

কাতারে ফাংশন যুক্ত করুন:

let _queue = [];

const _addToQueue = (funcToQ) => {
    _queue.push(funcToQ);
}

কার্যকর করুন এবং সারিটি ফ্লাশ করুন:

const _runQueue = () => {
    if (!_queue || !_queue.length) {
        return;
    }

    _queue.forEach(queuedFunc => {
        queuedFunc();
    });

    _queue = [];
}

এবং আপনি _ এডডটোকিউউটি চালানোর সময় আপনি কলব্যাকটি মোড়তে চাইবেন:

_addToQueue(() => methodYouWantToCallLater(<pass any args here like you normally would>));

আপনি যখন শর্তটি পূরণ করেছেন, কল করুন _runQueue()

এটি আমার পক্ষে দরকারী কারণ আমার বেশ কয়েকটি জিনিস একই পরিস্থিতিতে অপেক্ষা করার দরকার ছিল। এবং এটি যখন শর্তটি আঘাত হানে তখন মৃত্যুদন্ড কার্যকর করা দরকার যা কিছু থেকে শর্তটি সনাক্তকরণকে ডিউপল করে।


0

//function a(callback){
setTimeout(function() {
  console.log('Hi I am order 1');
}, 3000);
 // callback();
//}

//function b(callback){
setTimeout(function() {
  console.log('Hi I am order 2');
}, 2000);
//   callback();
//}



//function c(callback){
setTimeout(function() {
  console.log('Hi I am order 3');
}, 1000);
//   callback();

//}

 
/*function d(callback){
  a(function(){
    b(function(){
      
      c(callback);
      
    });
    
  });
  
  
}
d();*/


async function funa(){
  
  var pr1=new Promise((res,rej)=>{
    
   setTimeout(()=>res("Hi4 I am order 1"),3000)
        
  })
  
  
   var pr2=new Promise((res,rej)=>{
    
   setTimeout(()=>res("Hi4 I am order 2"),2000)
        
  })
   
    var pr3=new Promise((res,rej)=>{
    
   setTimeout(()=>res("Hi4 I am order 3"),1000)
        
  })

              
  var res1 = await pr1;
  var res2 = await pr2;
  var res3 = await pr3;
  console.log(res1,res2,res3);
  console.log(res1);
   console.log(res2);
   console.log(res3);

}   
    funa();
              


async function f1(){
  
  await new Promise(r=>setTimeout(r,3000))
    .then(()=>console.log('Hi3 I am order 1'))
    return 1;                        

}

async function f2(){
  
  await new Promise(r=>setTimeout(r,2000))
    .then(()=>console.log('Hi3 I am order 2'))
         return 2;                   

}

async function f3(){
  
  await new Promise(r=>setTimeout(r,1000))
    .then(()=>console.log('Hi3 I am order 3'))
        return 3;                    

}

async function finaloutput2(arr){
  
  return await Promise.all([f3(),f2(),f1()]);
}

//f1().then(f2().then(f3()));
//f3().then(f2().then(f1()));
  
//finaloutput2();

//var pr1=new Promise(f3)







async function f(){
  console.log("makesure");
  var pr=new Promise((res,rej)=>{
  setTimeout(function() {
  console.log('Hi2 I am order 1');
}, 3000);
  });
    
  
  var result=await pr;
  console.log(result);
}

 // f(); 

async function g(){
  console.log("makesure");
  var pr=new Promise((res,rej)=>{
  setTimeout(function() {
  console.log('Hi2 I am order 2');
}, 2000);
  });
    
  
  var result=await pr;
  console.log(result);
}
  
// g(); 

async function h(){
  console.log("makesure");
  var pr=new Promise((res,rej)=>{
  setTimeout(function() {
  console.log('Hi2 I am order 3');
}, 1000);
  });
    
  
  var result=await pr;
  console.log(result);
}

async function finaloutput(arr){
  
  return await Promise.all([f(),g(),h()]);
}
  
//finaloutput();

 //h(); 
  
  
  
  
  
  


0

আমার উদাহরণে, আমি প্রতি সেকেন্ডে একটি নতুন পাল্টা মান লগ করি:

var promises_arr = [];
var new_cntr_val = 0;

// fill array with promises
for (let seconds = 1; seconds < 10; seconds++) {
    new_cntr_val = new_cntr_val + 5;    // count to 50
    promises_arr.push(new Promise(function (resolve, reject) {
        // create two timeouts: one to work and one to resolve the promise
        setTimeout(function(cntr) {
            console.log(cntr);
        }, seconds * 1000, new_cntr_val);    // feed setTimeout the counter parameter
        setTimeout(resolve, seconds * 1000);
    }));
}

// wait for promises to finish
Promise.all(promises_arr).then(function (values) {
    console.log("all promises have returned");
});

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