teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

文章編集

2021/12/14 11:05

投稿

miyabi-sun
miyabi-sun

スコア21445

answer CHANGED
@@ -1,13 +1,48 @@
1
+ 落ちてる原因って本当にメモリ不足なんですかね?
2
+
3
+ そりゃいつかはメモリ解放出来ずに死ぬとは思いますが、
1
4
  これ再帰関数みたいな無限ループみたいになってて
2
- スコープを作り続けるから5桁回数回るくらいまででエラー吐いて落ちるんじゃないですか
5
+ スコープを作り続けるから5桁回数回るくらいまででエラー吐いて落ちるんじゃないですか?
3
6
 
7
+ ---
8
+
9
+ さて、解決にあたってですが
10
+ `setInterval`が使えれば話は早いですが、
11
+ update処理の実行にもたつくと2回、3回と溜まってしまうのが悩みどころ
12
+
4
13
  コールバック関数の仕組みだけで
5
- このパターンを解消するのはちとしんどい
14
+ このパターンを解消するのはちとしんどいですね。
15
+ 骨子はこんな感じ?
16
+
17
+ ```js
18
+ const id = (() => {
19
+ let ready = true;
20
+ return setInterval(
21
+ () => {
22
+ if (!ready) return;
23
+ ready = false;
24
+ update();
25
+ setTimeout(() => ready = true, (10 * 1000));
26
+ },
27
+ 50
28
+ );
29
+ )();
30
+
31
+ // 止めたくなったらこれを実行すればお行儀よく停止できそう
32
+ process.on("SIGINT", () => {
33
+ creaInterval(id);
34
+ });
35
+ ```
36
+
37
+ そこでわかり易さ重視で
6
38
  Promise→async/awaitを併用したパターンで作ってみました。
7
39
 
8
40
  ```js
9
- // 覚えさせたいデータはお外のスコープ準備
41
+ // 覚えさせたいデータがあれば外のスコープに変数を準備
10
- const state = {};
42
+ const state = {
43
+ foo: null,
44
+ update: true,
45
+ };
11
46
 
12
47
  // async関数を定義して返り値をPromiseにする
13
48
  const update = async () => {
@@ -16,7 +51,8 @@
16
51
 
17
52
  for (let i = 0; i < 20/*変動値*/; i++) {
18
53
  const hoge = new HogeHoge(options);
54
+
19
- state.hoge.push(hoge.awesomeCalc());
55
+ state.foo.push(hoge.awesomeCalc());
20
56
  }
21
57
  }
22
58
 
@@ -27,14 +63,19 @@
27
63
  // asyncのアロー関数を定義して即時実行
28
64
  // これによりawait構文を有効にして待てるようにする
29
65
  (async () => {
30
- while (true) {
66
+ while (state.update) {
31
67
  // await Promiseインスタンスと記述すると、
32
68
  // Promiseの動作が全て完了するのを待ってくれる挙動をする
33
69
  await update();
34
70
  await timeout(1000 * 10);
35
71
  }
36
72
  })();
73
+
74
+ process.on("SIGINT", () => {
75
+ state.update = false;
76
+ });
37
77
  ```
38
78
 
79
+ JS・Node.jsのガベージコレクトの動作対象は参照の切れた値です
39
- こうすればスコープがネストしないので
80
+ こうすればスコープがネストせず自然に参照が切れるので
40
- いずれガベージコレクトのお掃除で消えてなくなるかと思います。
81
+ hoge達はいずれガベージコレクトのお掃除で消えてなくなるかと思います。