JavaScript - Thread, Asynchronous, Ticks

9

Situation

Studying about Thread , I understood that they are lines of execution within a process. Studying about Assincronismo em javascript , I understand that it does not support multiple Thread , but has loop de eventos . If we have an address, we would be able to do the same thing in the same way that we would be able to do this, / em> to run.

However, as @bfavaretto said in its answer , you do not want to say that it will run in {time} , but at the next moment the setTimeout({function}, {time}) is free.

Test

(function(){
    var start = null;

    var checkTicks = function(){
        start = new Date();         // SETA start COM DATA CORRENTE
        var s = start.getSplitDate();
        start = new Date(s['year'],s['month'],s['day'],s['hours'],s['minutes'],s['seconds']);

        setTimeout(showDiff, 1000); // DEFINE FUNÇÃO A SER EXECUTADA APOS 1s
        loop();                     // CHAMADO DE LOOP QUE DEVE DEMORAR 5s
    }

    var loop = function(){
        var stop = false;
        while(!stop){
            var current = new Date();
            var s = current.getSplitDate();
            current = new Date(s['year'], s['month'], s['day'], s['hours'], s['minutes'], s['seconds']);

            if(betweenDates(current.toTimestamp(), start.toTimestamp(), 's') > 5){ // SO PARA APOS DIFF DE 5s
                stop = true;
            }
        }
    }

    var showDiff = function(){
        var current = new Date();
        var s = current.getSplitDate();
        current = new Date(s['year'],s['month'],s['day'],s['hours'],s['minutes'],s['seconds']);

        console.log(start.toTimestamp());
        console.log(current.toTimestamp());

        console.log(betweenDates(current.toTimestamp(), start.toTimestamp(), 's')); // EXIBE DIFERENCA ENTRE start E current
    }

    checkTicks(); // INICIO O PROCESSO
})();

Console result

6

Doubt

  • Why was the result 6 since the loop de eventos command set setTimeout(showDiff, 1000); to be executed in 1s?
  • The% w_ of% was occupied by 5s, showDiff should not be executed immediately after?

Issue

If you do not want to change the value of the parameter,

Auxiliary

betweenDates

	function betweenDates(d1, d2, diff, returnLiteral){
	
		d1 		= d1.split(' ');	// Divide o timestamp em data e hora
		d1[0]	= d1[0].split('-');	// Separa as variacoes da data
		d1[1]	= d1[1].split(':');	// Separa as variacoes da hora
		d1		= d1[0].concat(d1[1]); // concatena os dois conteudos formando um array unico.
	
		d1 = new Date(d1[0],d1[1],d1[2],d1[3],d1[4],d1[5]); // gera o objeto date
		d1 = Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), d1.getHours(), d1.getMinutes(), d1.getSeconds()); // retona o time UTC corespondente da data.
		
		d2 		= d2.split(' ');
		d2[0]	= d2[0].split('-');
		d2[1]	= d2[1].split(':');
		d2		= d2[0].concat(d2[1]);
	
		d2 = new Date(d2[0],d2[1],d2[2],d2[3],d2[4],d2[5]);
		d2 = Date.UTC(d2.getFullYear(), d2.getMonth(), d2.getDate(), d2.getHours(), d2.getMinutes(), d2.getSeconds());
		
		var dDiff = d2 - d1; // calcula a diferenca entre as datas
		
		var out = {
			'y' : dDiff/1000/60/60/24/30/12,	// calculo para ano
			'm' : dDiff/1000/60/60/24/30,		// calculo para mes
			'd' : dDiff/1000/60/60/24,			// calculo para dia
			'h' : dDiff/1000/60/60,				// calculo para hora
			'i' : dDiff/1000/60,				// calculo para minuto
			's' : dDiff/1000/1					// calculo para segundo
		};
	
		out = Math.floor(out[diff]);	// Saida (inteiro do calculo)
		
		// Retorno
		if(out < 0 && !returnLiteral){
			return out*-1;
		}else{
			return out;
		}
	}

Date.prototype.getSplitDate

	Date.prototype.getSplitDate = function(){
		var day		= this.getDate();
		var month	= this.getMonth();
		var year	= this.getFullYear();
	
		var hours	= this.getHours();
		var minutes	= this.getMinutes();
		var seconds	= this.getSeconds();
	
		var o = {};
		o['day']	= day;
		o['month']	= month;
		o['year']	= year;
	
		o['hours']	= hours;
		o['minutes']= minutes;
		o['seconds']= seconds;
	
		return o;
	}

Date.prototype.toTimestamp

	Date.prototype.toTimestamp = function(short){
	
		var o = this.getSplitDate();
	
		var date = '####-##-## ##:##:##';
	
		date = o['year'].toString().lpad(0,4).mask(date);
		date = o['month'].toString().lpad(0,2).mask(date);
		date = o['day'].toString().lpad(0,2).mask(date);
	
		date = o['hours'].toString().lpad(0,2).mask(date);
		date = o['minutes'].toString().lpad(0,2).mask(date);
		date = o['seconds'].toString().lpad(0,2).mask(date);
	
		if(short){
			date = date.split(' ');
			return date[0];
		}else{
			return date;
		}
	}

String.prototype.mask

	String.prototype.mask = function(mask){
		var value = onlyNumber(this);
	
		for(var i = 0; i <= mask.substrCount('#'); i++){
	
			if(typeof(value[i]) === 'undefined'){
				break;
			} 
	
			var k = mask.indexOf('#');
			mask = mask.split('');
			mask[k] = value[i];
			mask = mask.join('');
		}
	
		return mask;
	}
    
asked by anonymous 12.11.2015 / 13:55

3 answers

5

I think the best way to clarify this problem is to highlight the difference between competition and parallelism and the difference between cooperative competition and > preemptive .

In parallel computing you have several things running at the same time (literally, multiprocessors) but not necessarily these computations will interact with each other.

If you are doing competing computations, you have more than one "execution line" running at any given time, but they may be running on a single processor. The run line runs a little, then it pauses, and line B rolls a little, so it goes.

Finally, in a situation where you have multiple lines of execution sharing a processor, this sharing may be cooperative or preemptive.

  • In a cooperative situation the execution lines explicitly give up the processor. In Javascript this occurs every time you make an asynchronous system call, which returns the pro loop control of events.
  • On the other hand, in a situation with preemptive competition the system can stop execution at any time. This is what happens with the processes in your operating system or in the traditional threads you already know.

Returning to your problem, what happened is that the loop function never returns the control to the event loop. It is a simple while and this while will continue to run until the stop condition is false. In the end, you've implemented a spin lock .

One way to solve this problem is to set a timeout between each iteration of the loop.

function meuloop(){
    var current = new Date();
    if(betweenDates(current.toTimestamp(), start.toTimestamp(), 's') < 5){
        // Peça para o loop de eventos continuar o  "meu loop" assim que puder.
        // Dessa forma, o loop de eventos tem a oportunidade de
        // rodar outros eventos também.
        setTimeout(meuloop, 0);
    }else{
        console.log("acabou");
    }
}

BTW, on the node you can also use the nextTick function rather than a timeout with zero:

proccess.nextTick(meuloop)
    
12.11.2015 / 14:43
5

Its betweenDates function is very imprecise, it never uses the millisecond information objects of type Date include. I did a test by changing your code a bit, and the result was 5.007 seconds:

(function(){
    var start = null;

    var checkTicks = function(){
        start = new Date();         // SETA start COM DATA CORRENTE
        setTimeout(showDiff, 1000); // DEFINE FUNÇÃO A SER EXECUTADA APOS 1s
        loop();                     // CHAMADO DE LOOP QUE DEVE DEMORAR 5s
    }

    var loop = function(){
        var stop = false;
        while(!stop){
            var current = new Date();
            if(betweenDates(current, start) > 5){ // SO PARA APOS DIFF DE 5s
                stop = true;
            }
        }
    }

    var showDiff = function(){
        var current = new Date();
        console.log(betweenDates(current, start)); // EXIBE DIFERENCA ENTRE start E current
    }

    checkTicks(); // INICIO O PROCESSO
})();

function betweenDates(d1, d2) {
    return (d1.getTime() - d2.getTime()) / 1000;
}

link

    
12.11.2015 / 17:27
-1

This video explains how an Event Loop works. An event loop is implemented during the video.

Thisisthecodeyouputattheendofthevideo.

var fs = require('fs'); class Queue { constructor() { this.events = []; } waitForEvents() { return true; } pushEvent(event) { this.events.push(event); } processNextEvent() { if (this.events.length > 0) { var event = this.events[0]; if (event.type === 'timeout') { if (Date.now() >= event.registeredTime + event.timeout) { this.events.shift(); event.fn(); } } } } } var queue = new Queue(); function setTimeout2(fn, timeout) { var event = { type: 'timeout', registeredTime: Date.now(), timeout: timeout, fn: fn }; queue.pushEvent(event); } // ================ // Program setTimeout2(function() { console.log('Timeout 1 ' + Date.now()); }, 1000); setTimeout2(function() { console.log('Timeout 2 ' + Date.now()); }, 1000); setTimeout2(function() { console.log('Timeout 3 ' + Date.now()); setTimeout2(function() { console.log('Timeout 4 ' + Date.now()); }, 2000); setTimeout2(function() { console.log('Timeout 5 ' + Date.now()); }, 2000); }, 1000); setTimeout2(function() { console.log('Timeout do Javascript'); }, 2000); fs.readFile('setTimeout.js', 'utf8', function(error, data) { console.log('Arquivo lido:'); console.log(data); }); console.log('Arquivo lido'); // ================ while (queue.waitForEvents()) { queue.processNextEvent(); }     
17.01.2017 / 00:31