কীভাবে `setInterval` সিঙ্কে আরও আচরণ করা যায়, বা কীভাবে পরিবর্তে` setTimeout` ব্যবহার করবেন?


91

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

আমি অনলাইনে পড়েছি setTimeoutযা আরও সঠিক, এবং আপনার setTimeoutকোনওভাবে লুপ থাকতে পারে । তবে, আমি একটি জেনেরিক সংস্করণ পাইনি যা এটি কীভাবে সম্ভব তা চিত্রিত করে।

মূলত আমার মতো কিছু ফাংশন রয়েছে:

//drums
setInterval(function {
  //code for the drums playing goes here
}, 8000);

//chords
setInterval(function {
  //code for the chords playing goes here
}, 1000);

//bass
setInterval(function {
  //code for the bass playing goes here
}, 500);

এটা অতি ভাল, প্রাথমিকভাবে, কিন্তু একটি মিনিট কোর্সের উপর শব্দ লক্ষণীয়ভাবে সিঙ্কের বাইরে হয়ে কাজ হিসাবে আমি করেছি পঠিত সঙ্গে ঘটে setInterval। আমি পড়েছি যা setTimeoutআরও ধারাবাহিকভাবে সঠিক হতে পারে।

কেউ কি setTimeoutঅনির্দিষ্টকালের জন্য কিছু লুপ করার জন্য আমাকে কেবল একটি প্রাথমিক উদাহরণ দেখাতে পারেন? বিকল্পভাবে, যদি setIntervalঅন্য কোনও ফাংশন সহ আরও সমকালীন ফলাফল অর্জনের কোনও উপায় থাকে তবে দয়া করে আমাকে জানান।


4
আপনি কী অর্জন করতে চান তা আমাদের দেখিয়ে কিছু কোড কেন পোস্ট করবেন না এবং আমরা আপনাকে আরও ভাল উত্তর দিতে পারি।
অ্যান্ডি

4
আমি অনলাইনে পড়েছি যে সেটটাইমআউট আরও সঠিক : আপনি কোথায় পড়েছেন? একটি লিঙ্ক অন্তর্ভুক্ত করুন। আমি ধরে নিচ্ছি যে এটি সম্ভবত আপনার ক্ষেত্রে setTimeoutকেসটি হ'ল পরবর্তী সময়সীমার জন্য সময়টি কীভাবে সাময়িকভাবে সামঞ্জস্য করা হয়েছিল তা নির্ধারণ করতে পারেন।
ম্যাট বার্ল্যান্ড

4
কি হবে requestAnimationFrame? আপনার requestAnimationFrameকলব্যাক চলার সময় অডিওর সময়টি আপনাকে কেবল উল্লেখ করতে হবে ।
জেস্পার

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

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

উত্তর:


181

আপনি setTimeoutপুনরাবৃত্তি ব্যবহার করে একটি লুপ তৈরি করতে পারেন :

function timeout() {
    setTimeout(function () {
        // Do Something Here
        // Then recall the parent function to
        // create a recursive loop.
        timeout();
    }, 1000);
}

সঙ্গে সমস্যা setInterval()এবং setTimeout()কোন গ্যারান্টি আপনার কোড নির্দিষ্ট সময়ের মধ্যে চালানো হবে আছে যে। setTimeout()এটিকে পুনরাবৃত্তভাবে ব্যবহার করে এবং কল করার মাধ্যমে আপনি নিশ্চিত হয়ে গেছেন যে কোডটির পরবর্তী পুনরাবৃত্তি শুরুর আগে সময়সীমার অভ্যন্তরে পূর্ববর্তী সমস্ত ক্রিয়াকলাপ সম্পূর্ণ হয়ে গেছে।


4
এই পদ্ধতি এবং ব্যবহারের মধ্যে পার্থক্য কী setInterval?
জেস্পার

4
এই পদ্ধতির সমস্যাটি হ'ল যদি ফাংশনটি সম্পূর্ণ হতে 1000 মিমি থেকে বেশি সময় নেয় তবে এটি সবই পেটে যায়। এটি প্রতি 1000ms চালানোর গ্যারান্টিযুক্ত নয়। সেটইন্টারভাল হয়।
টিজেসি

@ টিজেসি: আপনি যা অর্জন করতে চাইছেন তার উপর এটি অনেকটাই নির্ভর করে। এটি আরও গুরুত্বপূর্ণ হতে পারে যে পূর্ববর্তী ফাংশনটি পরবর্তী পুনরাবৃত্তির আগে শেষ হয়, না হয়।
ম্যাট বার্ল্যান্ড

4
@ টিজেসি সঠিক, তবে যদি আপনার পূর্ববর্তী ক্রিয়াকলাপগুলি setInterval()পুনরায় সম্পাদনের আগে সম্পূর্ণ না হয় তবে আপনার ভেরিয়েবল এবং / অথবা ডেটা সত্যিই দ্রুত সিঙ্ক থেকে বেরিয়ে যেতে পারে। উদাহরণস্বরূপ যদি আমি ডেটাটির জন্য অজ্যাক্স করছি এবং সার্ভারটি প্রতিক্রিয়া জানাতে 1 সেকেন্ডের বেশি সময় নেয়, setInterval()আমার পূর্ববর্তী ডেটা ব্যবহার করে আমার পরবর্তী ক্রিয়াকলাপ চালিয়ে যাওয়ার আগে প্রক্রিয়াজাতকরণ শেষ না হত। এই পদ্ধতির সাথে, এটি কোনও গ্যারান্টিযুক্ত নয় যে আপনার ফাংশনটি প্রতি সেকেন্ডে চালু হবে। যাইহোক, এটি গ্যারান্টিযুক্ত যে আপনার পূর্ববর্তী ডেটা পরবর্তী অন্তর শেষ হওয়ার আগে প্রক্রিয়া শেষ করবে।
War10ck

4
@ ওয়ার 10ck, একটি সংগীত ভিত্তিক পরিবেশ দেওয়া, আমি ধরে নিয়েছিলাম যে এটি ভেরিয়েবল বা এজাক্স কল সেট করতে ব্যবহৃত হবে না যেখানে অর্ডার মেলে।
টিজেসি

30

শুধুমাত্র পরিপূরক। আপনার যদি কোনও ভেরিয়েবল পাস করতে হয় এবং এটি পুনরাবৃত্তি করতে হয় তবে আপনি ঠিক তেমন করতে পারেন:

function start(counter){
  if(counter < 10){
    setTimeout(function(){
      counter++;
      console.log(counter);
      start(counter);
    }, 1000);
  }
}
start(0);

আউটপুট:

1
2
3
...
9
10

প্রতি সেকেন্ডে এক লাইন।


12

উভয়ই সময় খুব সঠিক হতে চলেছে না, setTimeoutতা আরও একটু নির্ভুল হওয়ার জন্য একটি উপায় হ'ল শেষ পুনরাবৃত্তির পরে কতক্ষণ দেরি হয়েছিল তা গণনা করা এবং তারপরে পরবর্তী পুনরাবৃত্তি যথাযথভাবে সামঞ্জস্য করা। উদাহরণ স্বরূপ:

var myDelay = 1000;
var thisDelay = 1000;
var start = Date.now();

function startTimer() {    
    setTimeout(function() {
        // your code here...
        // calculate the actual number of ms since last time
        var actual = Date.now() - start;
        // subtract any extra ms from the delay for the next cycle
        thisDelay = myDelay - (actual - myDelay);
        start = Date.now();
        // start the timer again
        startTimer();
    }, thisDelay);
}

সুতরাং প্রথমবার এটি অপেক্ষা করতে হবে (কমপক্ষে) 1000 এমএস, যখন আপনার কোডটি কার্যকর হবে, তখন 1038 এমএস বলুন কিছুটা দেরি হতে পারে, সুতরাং আমরা পরবর্তী চক্রের জন্য আমাদের বিলম্ব থেকে 46 এমএস বিয়োগ করব এবং পরবর্তী বিলম্ব হবে শুধুমাত্র 954 এমএস। এটি টাইমারকে দেরি করে গুলি চালানো থেকে বিরত রাখবে না (এটি আশা করা যায়) তবে আপনাকে বিলম্বটি পিলিং থেকে বিরত করতে সহায়তা করে। (দ্রষ্টব্য: আপনি যাচাই করতে চাইতে পারেন thisDelay < 0যার অর্থ হ'ল বিলম্বটি আপনার টার্গেটের বিলম্বের দ্বিগুণের চেয়ে বেশি ছিল এবং আপনি একটি চক্র মিস করেছেন - আপনি কীভাবে এই মামলাটি পরিচালনা করতে চান তা অবধি))।

অবশ্যই এটি আপনাকে বেশ কয়েকটি টাইমার সিঙ্কে রাখতে সহায়তা করবে না, সেক্ষেত্রে আপনি একই টাইমার দিয়ে কীভাবে সমস্তগুলি নিয়ন্ত্রণ করতে পারেন তা নির্ধারণ করতে চাইতে পারেন।

সুতরাং আপনার কোডটি দেখে আপনার সমস্ত বিলম্ব 500 এর একাধিক, যাতে আপনি এরকম কিছু করতে পারেন:

var myDelay = 500;
var thisDelay = 500;
var start = Date.now();
var beatCount = 0;

function startTimer() {    
    setTimeout(function() {
        beatCount++;
        // your code here...
        //code for the bass playing goes here  

        if (count%2 === 0) {
            //code for the chords playing goes here (every 1000 ms)
        }

        if (count%16) {
            //code for the drums playing goes here (every 8000 ms)
        }

        // calculate the actual number of ms since last time
        var actual = Date.now() - start;
        // subtract any extra ms from the delay for the next cycle
        thisDelay = myDelay - (actual - myDelay);
        start = Date.now();
        // start the timer again
        startTimer();
    }, thisDelay);
}

4
+1 ঝরঝরে পদ্ধতির। আমি কখনই পরবর্তী রানের সময়সীমার সময়সীমার অফসেট করার কথা ভাবি নি। এটি সম্ভবত আপনাকে যথাযথ পরিমাপের কাছাকাছি এনে দেবে যেহেতু আপনি জাভাস্ক্রিপ্ট বিবেচনা করতে পারেন মাল্টি-থ্রেডড নয় এবং একটি সুসংগত সময়ের ব্যবধানে আগুন দেওয়ার গ্যারান্টিযুক্ত নয়।
War10ck

এটা অসাধারণ! আমি এটি চেষ্টা করতে যাচ্ছি এবং আপনাকে কীভাবে তা জানাতে দেব। আমার কোডটি বিশাল, সুতরাং সম্ভবত কিছুক্ষণ সময় লাগবে
ব্যবহারকারীর 3084366

বিবেচনা করুন: নির্দিষ্ট কোডে এই কোডটি ট্রিগার করা (উপরের মতো সংশোধন করা হলেও) সময়-লুপটি আসলে সমস্যাটি সম্পর্কে চিন্তাভাবনা করার ভুল উপায় হতে পারে। এটি এমনও হতে পারে যে আপনার প্রতিটি বিরতির দৈর্ঘ্য "পরবর্তী সময়ের-কিছু-যা-হওয়ার-কারণে-খেলানো হবে বিয়োগ বর্তমান সময়কে" সেট করা উচিত।
mordm

আমি স্রেফ লিখেছি এমন সমাধানের আরও ভাল সংস্করণ আপনি তৈরি করেছেন। আমি পছন্দ করি যে আপনার পরিবর্তনশীল নামগুলি সংগীত থেকে ভাষা ব্যবহার করে এবং আপনি বিলম্ব করে এমন বিলম্বগুলি চেষ্টা করে পরিচালনা করেন যা আমি চেষ্টাও করি না।
মিগুয়েল ভ্যালেন্সিয়া

8

অডিও টাইমিংয়ের সাথে মোকাবিলা করার সর্বোত্তম উপায়টি ওয়েব অডিও এপিআই সহ, এটির একটি আলাদা ঘড়ি রয়েছে যা মূল থ্রেডে যা ঘটছে তা নির্বিশেষে সঠিক। এখানে ক্রিস উইলসনের একটি দুর্দান্ত ব্যাখ্যা, উদাহরণ ইত্যাদি রয়েছে:

http://www.html5rocks.com/en/tutorials/audio/schedolve/

আরও ওয়েব অডিও এপিআইয়ের জন্য এই সাইটের চারপাশে নজর রাখুন, আপনার পরে যা ঠিক তা করার জন্য এটি তৈরি করা হয়েছিল।


আমি সত্যিই আরও বেশি লোক এটিকে উত্সাহিত করতে চাই। setTimeoutঅপর্যাপ্ত থেকে মারাত্মকভাবে ওভার কমপ্লিক্স পর্যন্ত ব্যাপ্তি ব্যবহার করে উত্তরগুলি । নেটিভ ফাংশন ব্যবহার করা আরও অনেক ভাল ধারণার মতো মনে হয়। যদি API আপনার উদ্দেশ্যটি পরিপূর্ণ না করে, তবে আমি একটি নির্ভরযোগ্য তৃতীয় পক্ষের নির্ধারিত লাইব্রেরিটি অনুসন্ধান করার চেষ্টা করার পরামর্শ দেব।
ত্রিশটি


3

আপনার প্রয়োজন অনুযায়ী

কিছু আমাকে লুপ করতে সেটটাইমআউট ব্যবহারের একটি প্রাথমিক উদাহরণ আমাকে দেখান

আমাদের নীচের উদাহরণ রয়েছে যা আপনাকে সহায়তা করতে পারে

var itr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var  interval = 1000; //one second
itr.forEach((itr, index) => {

  setTimeout(() => {
    console.log(itr)
  }, index * interval)
})


1

আমি কাজের জীবনে এইভাবে ব্যবহার করি: এই ক্ষেত্রে "সাধারণ লুপগুলি ভুলে যান" এবং "সেটইন্টারভাল" এর এই সংমিশ্রণটি ব্যবহার করে "সেটটাইমআউট" এর অন্তর্ভুক্ত রয়েছে:

    function iAsk(lvl){
        var i=0;
        var intr =setInterval(function(){ // start the loop 
            i++; // increment it
            if(i>lvl){ // check if the end round reached.
                clearInterval(intr);
                return;
            }
            setTimeout(function(){
                $(".imag").prop("src",pPng); // do first bla bla bla after 50 millisecond
            },50);
            setTimeout(function(){
                 // do another bla bla bla after 100 millisecond.
                seq[i-1]=(Math.ceil(Math.random()*4)).toString();
                $("#hh").after('<br>'+i + ' : rand= '+(Math.ceil(Math.random()*4)).toString()+' > '+seq[i-1]);
                $("#d"+seq[i-1]).prop("src",pGif);
                var d =document.getElementById('aud');
                d.play();                   
            },100);
            setTimeout(function(){
                // keep adding bla bla bla till you done :)
                $("#d"+seq[i-1]).prop("src",pPng);
            },900);
        },1000); // loop waiting time must be >= 900 (biggest timeOut for inside actions)
    }

পিএস: বুঝুন যে (সেটটাইমআউট) এর আসল আচরণ: তারা সবাই একই সাথে শুরু হবে "তিন ব্লে ব্লা একই মুহুর্তে গণনা শুরু করবে" সুতরাং মৃত্যুদন্ড কার্যকর করার ব্যবস্থা করার জন্য আলাদা সময়সীমা তৈরি করুন।

পিএস 2: টাইমিং লুপের উদাহরণ, তবে একটি প্রতিক্রিয়ার লুপগুলির জন্য আপনি ইভেন্টগুলি ব্যবহার করতে পারেন, আশ্বাস দেওয়ার আশ্বাস দিন ..


1

সমাধান সঙ্গে টাইমআউট লুপ সমস্যা

// it will print 5 times 5.
for(var i=0;i<5;i++){
setTimeout(()=> 
console.log(i), 
2000)
}               // 5 5 5 5 5

// improved using let
for(let i=0;i<5;i++){
setTimeout(()=> 
console.log('improved using let: '+i), 
2000)
}

// improved using closure
for(var i=0;i<5;i++){
((x)=>{
setTimeout(()=> 
console.log('improved using closure: '+x), 
2000)
})(i);
} 


4
কোনও ধারণা কেন এটি ভেরি এবং লেটের মধ্যে আলাদা আচরণ করে?
জয়

4
@ জায়ে ... তাদের মধ্যে পার্থক্য হ'ল ভার ফাংশন স্কোপড এবং যাক ব্লককে স্কোপড করা হোক। আরও স্পষ্টতার জন্য আপনি माध्यम.com
@

1

অন্য কেউ যেমন উল্লেখ করেছেন, ওয়েব অডিও এপিআইতে আরও ভাল টাইমার রয়েছে।

তবে সাধারণভাবে, যদি এই ইভেন্টগুলি ধারাবাহিকভাবে ঘটে থাকে, তবে কীভাবে আপনি সেগুলি একই টাইমারে রাখবেন? আমি একটি পদক্ষেপ সিকোয়েন্সার কীভাবে কাজ করে তা নিয়ে ভাবছি ।

ব্যবহারিকভাবে, এটি কি এরকম কিছু দেখাচ্ছে?

var timer = 0;
var limit = 8000; // 8000 will be the point at which the loop repeats

var drumInterval = 8000;
var chordInterval = 1000;
var bassInterval = 500;

setInterval(function {
    timer += 500;

    if (timer == drumInterval) {
        // Do drum stuff
    }

    if (timer == chordInterval) {
        // Do chord stuff
    }

    if (timer == bassInterval) {
        // Do bass stuff
    }

    // Reset timer once it reaches limit
    if (timer == limit) {
        timer = 0;
    }

}, 500); // Set the timer to the smallest common denominator

0

function appendTaskOnStack(task, ms, loop) {
    window.nextTaskAfter = (window.nextTaskAfter || 0) + ms;

    if (!loop) {
        setTimeout(function() {
            appendTaskOnStack(task, ms, true);
        }, window.nextTaskAfter);
    } 
    else {
        if (task) 
            task.apply(Array(arguments).slice(3,));
        window.nextTaskAfter = 0;
    }
}

for (var n=0; n < 10; n++) {
    appendTaskOnStack(function(){
        console.log(n)
    }, 100);
}


4
আপনার সমাধান একটি ব্যাখ্যা খুব প্রশংসা করা হবে!
টন

-2

আমি মনে করি ফাংশন শেষে সময় শেষ হওয়ার চেয়ে ভাল।

function main(){
    var something; 
    make=function(walkNr){
         if(walkNr===0){
           // var something for this step      
           // do something
         }
         else if(walkNr===1){
           // var something for that step 
           // do something different
         }

         // ***
         // finally
         else if(walkNr===10){
           return something;
         }
         // show progress if you like
         setTimeout(funkion(){make(walkNr)},15,walkNr++);  
   }
return make(0);
}   

এই তিনটি ফাংশন প্রয়োজনীয় কারণ দ্বিতীয় ফাংশনের ওয়ারগুলি প্রতিবার ডিফল্ট মান দিয়ে ওভাররাইট করা হবে। প্রোগ্রাম পয়েন্টার সেটটাইমআউটে পৌঁছে গেলে এক ধাপ ইতিমধ্যে গণনা করা হয়। তাহলে কেবল পর্দার জন্য একটু সময় দরকার needs


-2

কোডে ভেরির পরিবর্তে লেট ব্যবহার করুন:

for(let i=1;i<=5;i++){setTimeout(()=>{console.log(i)},1000);}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.