回答編集履歴
2
根本的に質問文を取り違えてたので修正
answer
CHANGED
@@ -16,8 +16,6 @@
|
|
16
16
|
Sleepの代わりにやりたいことを予め関数として用意しておいて、
|
17
17
|
setTimeoutという関数と同時に利用します。
|
18
18
|
|
19
|
-
質問文を JavaScript / Node.js 流儀で書き直すとこんな感じ。
|
20
|
-
|
21
19
|
```JavaScript
|
22
20
|
flag = 0; // global - 他の部分で状態が変化する
|
23
21
|
var s = 30;
|
@@ -28,31 +26,37 @@
|
|
28
26
|
setTimeout(fn, s * 1000);
|
29
27
|
```
|
30
28
|
|
31
|
-
|
29
|
+
30秒後に起動した際、「ありゃ、フラグが0から変更されてるじゃん…起動やめよっと」と
|
32
30
|
判断して内部の処理を取りやめるフローに変更しています。
|
33
31
|
|
32
|
+
---
|
33
|
+
|
34
|
+
【ここから追記】
|
35
|
+
|
36
|
+
> sleep中であってもflagの値が変化したらsleepをやめるものです。
|
37
|
+
|
38
|
+
つまり、スリープをやめて今すぐ発火して欲しいのですね。
|
39
|
+
私の上の回答文ではやりたい事は満たせないですね……
|
40
|
+
そのように作り変えましょう!
|
41
|
+
|
34
42
|
setTimeoutの戻り値のIDを利用して、下記の様に登録したsetTimeoutを取り消す事も可能です。
|
35
|
-
|
43
|
+
つまり、登録はしておいたけどやっぱりキャンセルは可能なんですね。
|
44
|
+
後で使うので覚えておいてください。
|
36
45
|
|
37
46
|
```JavaScript
|
38
47
|
var fnId = setTimeout(fn, s * 1000);
|
39
48
|
clearTimeout(fnId);
|
40
49
|
```
|
41
50
|
|
42
|
-
---
|
43
|
-
|
44
|
-
追記: 俺はflag変数が変更されたらすぐに取り下げたいんだ!!
|
45
|
-
|
46
|
-
MobXというパッケージを導入しましょう。
|
51
|
+
そしてMobXというパッケージを導入しましょう。
|
47
|
-
おそらくこの縛りでは最善です。
|
48
52
|
参考サイト: [これからMobXをはじめる人へ](http://lealog.hateblo.jp/entry/2016/12/15/113825)
|
49
53
|
|
50
|
-
|
54
|
+
MobXのパッケージはReactという動的なページを表示するフレームワークのおまけみたいな扱いをされますが、本質は変数のオブザーバにあります。
|
51
|
-
本質は変数のオブザーバにあります。
|
52
|
-
オブザーバ
|
55
|
+
オブザーバというのは変数を常に監視して、値が変わったら即座に関数を実行するデザインパターンを指します。
|
53
56
|
|
54
|
-
|
57
|
+
30秒後に登録しておいたsetTimeoutの関数を取り下げつつ、今すぐ実行します。
|
58
|
+
因みにMobXに限らず自分で作ったイベントエミッター系は同期実行なのでsetTimeoutに割り込まれる事はなく、
|
55
|
-
|
59
|
+
30秒と同時にフラグが経って2回関数が叩かれるという残念な事は起こりません。
|
56
60
|
|
57
61
|
以前私が[イベントループを上手く回す為にベンチマークと称して使ってたコード](https://github.com/miyabisun/node-queue-benchmark/blob/master/test/MobX.js)がありますので、
|
58
62
|
流用してサクッと実装してみましょう。
|
@@ -65,20 +69,21 @@
|
|
65
69
|
global.store = observable({
|
66
70
|
flag: 0 // globalのflag変数はこっちに引っ越しました。少し使い勝手が変わるので注意
|
67
71
|
});
|
72
|
+
|
73
|
+
const fn = function() {
|
74
|
+
if (state.id == null) return;
|
75
|
+
state.id = null;
|
76
|
+
// do something
|
77
|
+
}
|
78
|
+
state.id = setTimeout(fn, 31000);
|
68
79
|
reaction(
|
69
80
|
() => store.flag,
|
70
81
|
() => {
|
71
82
|
if (store.flag === 0) return;
|
72
|
-
clearTimeout(state.id);
|
83
|
+
if (state.id) clearTimeout(state.id); // 先程実行したものを取り下げて
|
84
|
+
fn(); // 手動実行!
|
73
85
|
}
|
74
86
|
)
|
75
|
-
|
76
|
-
var s = 30;
|
77
|
-
var fn = function() {
|
78
|
-
if (flag != 0) return;
|
79
|
-
// dosomething
|
80
|
-
}
|
81
|
-
state.id = setTimeout(fn, s * 1000);
|
82
87
|
```
|
83
88
|
|
84
89
|
ざっとこんな感じですかね。
|
1
MobXを利用するように修正
answer
CHANGED
@@ -37,4 +37,48 @@
|
|
37
37
|
```JavaScript
|
38
38
|
var fnId = setTimeout(fn, s * 1000);
|
39
39
|
clearTimeout(fnId);
|
40
|
-
```
|
40
|
+
```
|
41
|
+
|
42
|
+
---
|
43
|
+
|
44
|
+
追記: 俺はflag変数が変更されたらすぐに取り下げたいんだ!!
|
45
|
+
|
46
|
+
MobXというパッケージを導入しましょう。
|
47
|
+
おそらくこの縛りでは最善です。
|
48
|
+
参考サイト: [これからMobXをはじめる人へ](http://lealog.hateblo.jp/entry/2016/12/15/113825)
|
49
|
+
|
50
|
+
このパッケージはReactという動的なページを表示するフレームワークのおまけみたいな扱いをされますが、
|
51
|
+
本質は変数のオブザーバにあります。
|
52
|
+
オブザーバってあれですよ、変数を常に監視して、値が変わったら処理を行う奴です。
|
53
|
+
|
54
|
+
このシチュエーション、flagという変数をひたすら見張って変更した瞬間に待機を停止したいのですよね?
|
55
|
+
これ以上の選択肢は無いと言って過言ではありません。
|
56
|
+
|
57
|
+
以前私が[イベントループを上手く回す為にベンチマークと称して使ってたコード](https://github.com/miyabisun/node-queue-benchmark/blob/master/test/MobX.js)がありますので、
|
58
|
+
流用してサクッと実装してみましょう。
|
59
|
+
|
60
|
+
```JavaScript
|
61
|
+
const {observable, autorun, reaction} = require('mobx');
|
62
|
+
global.state = {
|
63
|
+
id: null
|
64
|
+
};
|
65
|
+
global.store = observable({
|
66
|
+
flag: 0 // globalのflag変数はこっちに引っ越しました。少し使い勝手が変わるので注意
|
67
|
+
});
|
68
|
+
reaction(
|
69
|
+
() => store.flag,
|
70
|
+
() => {
|
71
|
+
if (store.flag === 0) return;
|
72
|
+
clearTimeout(state.id);
|
73
|
+
}
|
74
|
+
)
|
75
|
+
|
76
|
+
var s = 30;
|
77
|
+
var fn = function() {
|
78
|
+
if (flag != 0) return;
|
79
|
+
// dosomething
|
80
|
+
}
|
81
|
+
state.id = setTimeout(fn, s * 1000);
|
82
|
+
```
|
83
|
+
|
84
|
+
ざっとこんな感じですかね。
|