回答編集履歴
2
根本的に質問文を取り違えてたので修正
test
CHANGED
@@ -34,10 +34,6 @@
|
|
34
34
|
|
35
35
|
|
36
36
|
|
37
|
-
質問文を JavaScript / Node.js 流儀で書き直すとこんな感じ。
|
38
|
-
|
39
|
-
|
40
|
-
|
41
37
|
```JavaScript
|
42
38
|
|
43
39
|
flag = 0; // global - 他の部分で状態が変化する
|
@@ -58,15 +54,37 @@
|
|
58
54
|
|
59
55
|
|
60
56
|
|
61
|
-
|
57
|
+
30秒後に起動した際、「ありゃ、フラグが0から変更されてるじゃん…起動やめよっと」と
|
62
58
|
|
63
59
|
判断して内部の処理を取りやめるフローに変更しています。
|
64
60
|
|
65
61
|
|
66
62
|
|
63
|
+
---
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
【ここから追記】
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
> sleep中であってもflagの値が変化したらsleepをやめるものです。
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
つまり、スリープをやめて今すぐ発火して欲しいのですね。
|
76
|
+
|
77
|
+
私の上の回答文ではやりたい事は満たせないですね……
|
78
|
+
|
79
|
+
そのように作り変えましょう!
|
80
|
+
|
81
|
+
|
82
|
+
|
67
83
|
setTimeoutの戻り値のIDを利用して、下記の様に登録したsetTimeoutを取り消す事も可能です。
|
68
84
|
|
69
|
-
|
85
|
+
つまり、登録はしておいたけどやっぱりキャンセルは可能なんですね。
|
86
|
+
|
87
|
+
後で使うので覚えておいてください。
|
70
88
|
|
71
89
|
|
72
90
|
|
@@ -80,33 +98,23 @@
|
|
80
98
|
|
81
99
|
|
82
100
|
|
83
|
-
---
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
追記: 俺はflag変数が変更されたらすぐに取り下げたいんだ!!
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
MobXというパッケージを導入しましょう。
|
101
|
+
そしてMobXというパッケージを導入しましょう。
|
92
|
-
|
93
|
-
おそらくこの縛りでは最善です。
|
94
102
|
|
95
103
|
参考サイト: [これからMobXをはじめる人へ](http://lealog.hateblo.jp/entry/2016/12/15/113825)
|
96
104
|
|
97
105
|
|
98
106
|
|
99
|
-
|
107
|
+
MobXのパッケージはReactという動的なページを表示するフレームワークのおまけみたいな扱いをされますが、本質は変数のオブザーバにあります。
|
100
108
|
|
101
|
-
本質は変数のオブザーバにあります。
|
102
|
-
|
103
|
-
オブザーバ
|
109
|
+
オブザーバというのは変数を常に監視して、値が変わったら即座に関数を実行するデザインパターンを指します。
|
104
110
|
|
105
111
|
|
106
112
|
|
107
|
-
|
113
|
+
30秒後に登録しておいたsetTimeoutの関数を取り下げつつ、今すぐ実行します。
|
108
114
|
|
115
|
+
因みにMobXに限らず自分で作ったイベントエミッター系は同期実行なのでsetTimeoutに割り込まれる事はなく、
|
116
|
+
|
109
|
-
|
117
|
+
30秒と同時にフラグが経って2回関数が叩かれるという残念な事は起こりません。
|
110
118
|
|
111
119
|
|
112
120
|
|
@@ -132,6 +140,20 @@
|
|
132
140
|
|
133
141
|
});
|
134
142
|
|
143
|
+
|
144
|
+
|
145
|
+
const fn = function() {
|
146
|
+
|
147
|
+
if (state.id == null) return;
|
148
|
+
|
149
|
+
state.id = null;
|
150
|
+
|
151
|
+
// do something
|
152
|
+
|
153
|
+
}
|
154
|
+
|
155
|
+
state.id = setTimeout(fn, 31000);
|
156
|
+
|
135
157
|
reaction(
|
136
158
|
|
137
159
|
() => store.flag,
|
@@ -140,25 +162,13 @@
|
|
140
162
|
|
141
163
|
if (store.flag === 0) return;
|
142
164
|
|
143
|
-
clearTimeout(state.id);
|
165
|
+
if (state.id) clearTimeout(state.id); // 先程実行したものを取り下げて
|
166
|
+
|
167
|
+
fn(); // 手動実行!
|
144
168
|
|
145
169
|
}
|
146
170
|
|
147
171
|
)
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
var s = 30;
|
152
|
-
|
153
|
-
var fn = function() {
|
154
|
-
|
155
|
-
if (flag != 0) return;
|
156
|
-
|
157
|
-
// dosomething
|
158
|
-
|
159
|
-
}
|
160
|
-
|
161
|
-
state.id = setTimeout(fn, s * 1000);
|
162
172
|
|
163
173
|
```
|
164
174
|
|
1
MobXを利用するように修正
test
CHANGED
@@ -77,3 +77,91 @@
|
|
77
77
|
clearTimeout(fnId);
|
78
78
|
|
79
79
|
```
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
---
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
追記: 俺はflag変数が変更されたらすぐに取り下げたいんだ!!
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
MobXというパッケージを導入しましょう。
|
92
|
+
|
93
|
+
おそらくこの縛りでは最善です。
|
94
|
+
|
95
|
+
参考サイト: [これからMobXをはじめる人へ](http://lealog.hateblo.jp/entry/2016/12/15/113825)
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
このパッケージはReactという動的なページを表示するフレームワークのおまけみたいな扱いをされますが、
|
100
|
+
|
101
|
+
本質は変数のオブザーバにあります。
|
102
|
+
|
103
|
+
オブザーバってあれですよ、変数を常に監視して、値が変わったら処理を行う奴です。
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
このシチュエーション、flagという変数をひたすら見張って変更した瞬間に待機を停止したいのですよね?
|
108
|
+
|
109
|
+
これ以上の選択肢は無いと言って過言ではありません。
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
以前私が[イベントループを上手く回す為にベンチマークと称して使ってたコード](https://github.com/miyabisun/node-queue-benchmark/blob/master/test/MobX.js)がありますので、
|
114
|
+
|
115
|
+
流用してサクッと実装してみましょう。
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
```JavaScript
|
120
|
+
|
121
|
+
const {observable, autorun, reaction} = require('mobx');
|
122
|
+
|
123
|
+
global.state = {
|
124
|
+
|
125
|
+
id: null
|
126
|
+
|
127
|
+
};
|
128
|
+
|
129
|
+
global.store = observable({
|
130
|
+
|
131
|
+
flag: 0 // globalのflag変数はこっちに引っ越しました。少し使い勝手が変わるので注意
|
132
|
+
|
133
|
+
});
|
134
|
+
|
135
|
+
reaction(
|
136
|
+
|
137
|
+
() => store.flag,
|
138
|
+
|
139
|
+
() => {
|
140
|
+
|
141
|
+
if (store.flag === 0) return;
|
142
|
+
|
143
|
+
clearTimeout(state.id);
|
144
|
+
|
145
|
+
}
|
146
|
+
|
147
|
+
)
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
var s = 30;
|
152
|
+
|
153
|
+
var fn = function() {
|
154
|
+
|
155
|
+
if (flag != 0) return;
|
156
|
+
|
157
|
+
// dosomething
|
158
|
+
|
159
|
+
}
|
160
|
+
|
161
|
+
state.id = setTimeout(fn, s * 1000);
|
162
|
+
|
163
|
+
```
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
ざっとこんな感じですかね。
|