1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

Adds setInterval, clearInterval, clearTimeout.

This commit is contained in:
Parsa Ghadimi 2018-05-23 23:23:41 +04:30 committed by Ryan Dahl
parent 3171ba4c3f
commit cb222ceb22
7 changed files with 126 additions and 19 deletions

View file

@ -1,4 +1,4 @@
import { setTimeout } from "./timers"; import * as timer from "./timers";
// If you use the eval function indirectly, by invoking it via a reference // If you use the eval function indirectly, by invoking it via a reference
// other than eval, as of ECMAScript 5 it works in the global scope rather than // other than eval, as of ECMAScript 5 it works in the global scope rather than
@ -14,7 +14,10 @@ export const _global = globalEval("this");
_global["window"] = _global; // Create a window object. _global["window"] = _global; // Create a window object.
import "./url"; import "./url";
_global["setTimeout"] = setTimeout; _global["setTimeout"] = timer.setTimeout;
_global["setInterval"] = timer.setInterval;
_global["clearTimeout"] = timer.clearTimer;
_global["clearInterval"] = timer.clearTimer;
const print = V8Worker2.print; const print = V8Worker2.print;

View file

@ -16,6 +16,7 @@ message Msg {
ExitMsg exit = 14; ExitMsg exit = 14;
TimerStartMsg timer_start = 15; TimerStartMsg timer_start = 15;
TimerReadyMsg timer_ready = 16; TimerReadyMsg timer_ready = 16;
TimerClearMsg timer_clear = 17;
} }
} }
@ -60,3 +61,5 @@ message TimerReadyMsg {
optional int32 id = 1; optional int32 id = 1;
optional bool done = 2; optional bool done = 2;
} }
message TimerClearMsg { optional int32 id = 1; }

View file

@ -3,3 +3,9 @@ setTimeout(function() {
}, 10); }, 10);
console.log("Hello"); console.log("Hello");
const id = setTimeout(function() {
console.log("Not printed");
}, 10000);
clearTimeout(id);

7
testdata/010_set_interval.ts vendored Normal file
View file

@ -0,0 +1,7 @@
const id = setInterval(function() {
console.log("test")
}, 200);
setTimeout(function() {
clearInterval(id)
}, 500)

2
testdata/010_set_interval.ts.out vendored Normal file
View file

@ -0,0 +1,2 @@
test
test

View file

@ -5,6 +5,16 @@ import (
"time" "time"
) )
type Timer struct {
Id int32
Done bool
Cleared bool
Interval bool
Duration int32 // In milliseconds
}
var timers = make(map[int32]*Timer)
func InitTimers() { func InitTimers() {
Sub("timers", func(buf []byte) []byte { Sub("timers", func(buf []byte) []byte {
msg := &Msg{} msg := &Msg{}
@ -12,28 +22,62 @@ func InitTimers() {
switch msg.Payload.(type) { switch msg.Payload.(type) {
case *Msg_TimerStart: case *Msg_TimerStart:
payload := msg.GetTimerStart() payload := msg.GetTimerStart()
return HandleTimerStart(*payload.Id, *payload.Interval, timers[*payload.Id] = &Timer{
*payload.Duration) Id: *payload.Id,
Done: false,
Interval: *payload.Interval,
Duration: *payload.Duration,
Cleared: false,
}
timers[*payload.Id].StartTimer()
return nil
case *Msg_TimerClear:
payload := msg.GetTimerClear()
// TODO maybe need mutex here.
timer := timers[*payload.Id]
timer.Clear()
return nil
default: default:
panic("[timers] Unexpected message " + string(buf)) panic("[timers] Unexpected message " + string(buf))
} }
}) })
} }
func HandleTimerStart(id int32, interval bool, duration int32) []byte { func (t *Timer) Clear() {
if !t.Cleared {
wg.Done()
t.Cleared = true
delete(timers, t.Id)
}
t.Done = true
}
func (t *Timer) StartTimer() {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer t.Clear()
time.Sleep(time.Duration(duration) * time.Millisecond) for {
payload, err := proto.Marshal(&Msg{ time.Sleep(time.Duration(t.Duration) * time.Millisecond)
if !t.Interval {
t.Done = true
}
pubMsg(&Msg{
Payload: &Msg_TimerReady{ Payload: &Msg_TimerReady{
TimerReady: &TimerReadyMsg{ TimerReady: &TimerReadyMsg{
Id: &id, Id: &t.Id,
Done: &t.Done,
}, },
}, },
}) })
if t.Done {
return
}
}
}()
}
func pubMsg(msg *Msg) {
payload, err := proto.Marshal(msg)
check(err) check(err)
Pub("timers", payload) Pub("timers", payload)
}()
return nil
} }

View file

@ -4,12 +4,14 @@ import * as dispatch from "./dispatch";
let nextTimerId = 1; let nextTimerId = 1;
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
type TimerCallback = (...args: any[]) => void; export type TimerCallback = (...args: any[]) => void;
interface Timer { interface Timer {
id: number; id: number;
cb: TimerCallback; cb: TimerCallback;
interval: boolean; interval: boolean;
// tslint:disable-next-line:no-any
args: any[];
duration: number; // milliseconds duration: number; // milliseconds
} }
@ -23,17 +25,26 @@ function onMessage(payload: Uint8Array) {
const msg = pb.Msg.decode(payload); const msg = pb.Msg.decode(payload);
const { id, done } = msg.timerReady; const { id, done } = msg.timerReady;
const timer = timers.get(id); const timer = timers.get(id);
timer.cb(); if (!timer) {
return;
}
timer.cb(...timer.args);
if (done) { if (done) {
timers.delete(id); timers.delete(id);
} }
} }
export function setTimeout(cb: TimerCallback, duration: number): number { export function setTimeout(
cb: TimerCallback,
duration: number,
// tslint:disable-next-line:no-any
...args: any[]
): number {
const timer = { const timer = {
id: nextTimerId++, id: nextTimerId++,
interval: false, interval: false,
duration, duration,
args,
cb cb
}; };
timers.set(timer.id, timer); timers.set(timer.id, timer);
@ -46,3 +57,34 @@ export function setTimeout(cb: TimerCallback, duration: number): number {
}); });
return timer.id; return timer.id;
} }
// TODO DRY with setTimeout
export function setInterval(
cb: TimerCallback,
repeat: number,
// tslint:disable-next-line:no-any
...args: any[]
): number {
const timer = {
id: nextTimerId++,
interval: true,
duration: repeat,
args,
cb
};
timers.set(timer.id, timer);
dispatch.sendMsg("timers", {
timerStart: {
id: timer.id,
interval: true,
duration: repeat
}
});
return timer.id;
}
export function clearTimer(id: number) {
dispatch.sendMsg("timers", {
timerClear: { id }
});
}