質問編集履歴

7

問題自体に不備があったため、質問の意図の変更

2022/11/05 02:32

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
@@ -1 +1 @@
1
- メインプロセス取得したデータをレンダラープロセスに返す方法
1
+ Electronのメインプロセスで非同期処理なallメソッドでデータを取得してレンダラープロセスに返す方法
test CHANGED
@@ -1,31 +1,22 @@
1
1
  ### 前提
2
+
3
+ (問題自体に不備があったので質問の意図自体を変更します)
2
4
 
3
5
  Electron (node.js)初挑戦です。sqlite3を使いたいと思い、npmを使ってインストールしました。
4
6
  サンプルとしてそのsqlite3を使ってデータベースからselectをした結果を取得しようとしています。
5
7
 
6
8
  ### 実現したいこと
7
9
 
10
+ - [ ] 前提にある問題(非同期であるため処理が前後していて、値がおかしいこと)の解決
8
- - [ ] (最終的には)let txt値を最終的呼び出相当するrenderer.jsに返したい
11
+  → ようにして安全データをmain.jsからrenderer.jsを渡すか
9
- - [ ] 双方向にやり取りをするにはinvokeとhandleを使って行うのはわかっているが、なぜかmain.jsから送れない(ため、その問題を解決したい)
10
- ~~- [ ] C++でいう[ラムダ式](https://cpprefjp.github.io/lang/cpp11/lambda_expressions.html)で用いるキャプチャのような機能はどのようにすべきか~~
11
-
12
-
13
- 今までJavaScriptは触っても(ループ系は)for文ぐらいしかやっていなかったので戸惑っています。
14
12
 
15
13
  ### 発生している問題・エラーメッセージ
16
14
 
15
+ main.js内のipcMain.handleメソッド内でsqlite3を使う処理をして、renderer.jsでinvokeして起動します。
16
+ ただ、(sqliteからselectするために使う)sqlite3.Database#allメソッド等は非同期らしく、allメソッドの次の処理と前後が逆になることがあり、renderer.jsに戻り値として返されるデータが常に空か``{}``のような中身のないデータになっています。
17
+
18
+ 「Electron node.js sqlite3」と調べてもよくて、Electronの古いバージョンでのサンプル(renderer.jsに直接requireするとか)か、単に``db.all("select * from users", (error, rows) =>{ console.log( rows ); });``のように、「ラムダ式の中でそのまま出力するだけ」となっています。
17
- 「該当のソスコード」「HERE!」とあ場所txtにレコード一行レベルで文字列に固め最終的に
19
+ タを取り出すだけならいいですが、非同期処理なので値が入ったり入らなかったりすそこで頭悩ませいます。
18
-
19
- ```
20
- txtの値:
21
- name = 太郎, email = ****, age = 19
22
- name = 次郎, email = ****, age = 20
23
- ...
24
- ```
25
- のような感じで一つの文字列にしたいです。(最終的に使うものは配列でOKですが)
26
-
27
- ここで問題になるのはallメソッドに渡されたラムダ式からすると外部変数(?)にあたるtxtに値を追加したいということです。~~C++だと キャプチャを使って``auto f = [&a] { return a; };``のように使えますが、JavaScript(or node.js)ではこの処理はできないのでしょうか?~~
28
- キャプチャはできているようなので、それを呼び出し側であるrenderer.jsに返したいのですが、恐らく下の追記1のコードではallメソッド内のtxtとその親の関数内のtxtは別のものと認識されているため、空で返されます。
29
20
 
30
21
  ### 該当のソースコード
31
22
 
@@ -120,17 +111,15 @@
120
111
  */
121
112
 
122
113
  // HERE!
123
- let txt = "";
114
+ let txt = ""; // ①
124
115
  db.all("select * from users", (error, rows) =>{
125
- rows.forEach(row => { txt += "hello"; });
116
+ rows.forEach(row => { txt += "hello"; }); // ②
126
- });
117
+ });
127
- console.log( "select = " + txt );
118
+ console.log( "select = " + txt ); // ③
128
119
  });
129
120
  return false;
130
121
  });
131
122
  };
132
-
133
-
134
123
 
135
124
  // 初期化が完了した時の処理
136
125
  app.whenReady().then(() => {
@@ -232,18 +221,21 @@
232
221
  ### 試したこと
233
222
 
234
223
  [やったこと1]
235
- まま return rows; とやた。(つまりデータを文字列化するはrendererに任せる)
224
+ (最初はラムダ式外にあるlet txtに入ていないかと思い、質問して)txtの値を確認した
236
225
  ```JavaScript
237
226
  db.all("select * from users", (error, rows) =>{
238
227
  console.log( "all" );
239
228
  rows.forEach(row => { txt += "hello"; });
229
+ console.log( txt );
240
- });
230
+ });
231
+ console.log( "out: " + txt );
241
232
  ```
242
233
  [結果1]
243
234
  renderer.js内のselectRecordメソッドでのconsole.log( result );ではfalseが表示され、コンソールには
244
235
  ```
245
- text =
236
+ out:
246
237
  all
238
+ hellohello
247
239
  ```
248
240
  と空になっていた。(それとラムダ式の関数が後から動いているらしい。つまり順番が違う。)
249
241
 
@@ -265,47 +257,65 @@
265
257
  [結果3]
266
258
  結果1,2と同じ。
267
259
 
268
-
260
+ [やったこと4]
261
+ ラムダ式内のtxtからするとipcMain.handle内のtxtは別の変数(グローバル変数のような感じ)と解釈されたのだと思い、main.jsの先頭に``"use strict";``を付けてみた。
262
+
263
+ [結果4]
264
+ 変わらず。
265
+
266
+ [やったこと5]
267
+ [公式ドキュメント](https://www.npmjs.com/package/sqlite3)からall系の一括読み込みメソッドを調べた。
268
+
269
+ [結果5]
270
+ 探した範囲では存在しなかった。(コールバック関数を受け取って非同期的に行うものしかなかった。)
271
+
272
+ [やったこと6]
273
+ (非同期処理であり、コールバック関数としてラムダ式が渡されていることから)通常の関数として切り出して、renderer.js側でコールバック関数として定義し、ipcRenderer.invokeの引数として渡して処理させる。
274
+
275
+ ```
276
+ // renderer.jsから抜粋
277
+
278
+ function callback( err, rows ){
279
+ console.log( rows ); // 本来はここで何らかの処理をする
280
+ }
281
+
282
+ ...
283
+
284
+ selectRecord : () => {
285
+ ipcRenderer.invoke( "select_record", callback ).then( (result) => {
286
+ console.log( result );
287
+ });
288
+ }
289
+ ```
290
+
291
+ ```
292
+ // main.jsから抜粋
293
+ ipcMain.handle( "select_record", (_evnet, f) => {
294
+ db.serialize( function(){
295
+ let txt = "";
296
+ db.all("select * from users", (error, rows) =>{
297
+ f( error, rows );
298
+ });
299
+ //console.log( "select = " + txt );
300
+ });
301
+ return false;
302
+ });
303
+ ```
304
+
305
+ [結果6]
306
+ ``VM4 sandbox_bundle:29 Uncaught (in promise) Error: An object could not be cloned.``というエラーメッセージがディベロッパーツール上に表示される。
307
+ → 調べるとメインプロセスとレンダラープロセスは分断されているために起こるエラー。ただし仕様上のものなので対処できないらしい?
308
+
309
+ [やったこと7]
310
+ 念のためdb.serializeに渡している無名関数の引数としてfを指定した。
311
+
312
+ [結果7]
313
+ 結果6と同様。
314
+
315
+ 後思いつく方法としては『メインプロセスでDB操作を行いながら、直接DOM操作も行う』という方法ですが、できればメインプロセスはウィンドウの処理をして、DOM操作を行うのはレンダラープロセスに任せたいのです。
269
316
 
270
317
  ### 補足情報(FW/ツールのバージョンなど)
271
318
 
272
319
  言語: JavaScript
273
320
  node.js : node v16.17.0
274
321
  Electron: Electron v21.1.1
275
-
276
- ----------------
277
-
278
- [追記1]
279
-
280
- su507さんがご提示してくださったようにconsole.logをallメソッド内の処理として移動させると確かに表示されますが、最終的には呼び出し側に相当するrenderer.jsにtxtの値を渡したいのです。
281
-
282
- ```
283
- // やったこと4
284
-
285
- let txt = "";
286
- db.all("select * from users", (error, rows) =>{
287
- rows.forEach(row => { txt += "hello"; });
288
- console.log( "select = " + txt ); // ①
289
- });
290
-
291
- // ②
292
- return txt;
293
-
294
- /*
295
- 結果:
296
- 確かに ①で"select = hellohello" と表示されるが、できれば②でrenderer.jsに返したい。
297
- */
298
- ```
299
-
300
- 多分、ラムダ式内では別の変数として扱われ、allに渡されたラムダ式のスコープから抜けるので``let txt``側の値になっているのだと思いますが、allの外にある``let txt``の値を変化させたいのですが…
301
- (うまく伝えられなくてすみません)
302
-
303
- -----
304
-
305
- [追記2]
306
-
307
- ラムダ式内のtxtからするとipcMain.handle内のtxtは別の変数(グローバル変数のような感じ)と解釈されたのだと思い、main.jsの先頭に``"use strict";``を付けてやってみましたが改善されず。
308
-
309
- 恐らく**コールバック関数としてのラムダ式が呼ばれる時期が違うため**だと思いますがこれはどのように制御すべきなのでしょうか? それとも呼び出し方が悪いのでしょうか?
310
-
311
-

6

追記2

2022/11/03 23:48

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
File without changes
test CHANGED
@@ -300,6 +300,12 @@
300
300
  多分、ラムダ式内では別の変数として扱われ、allに渡されたラムダ式のスコープから抜けるので``let txt``側の値になっているのだと思いますが、allの外にある``let txt``の値を変化させたいのですが…
301
301
  (うまく伝えられなくてすみません)
302
302
 
303
-
303
+ -----
304
+
304
-
305
+ [追記2]
306
+
305
-
307
+ ラムダ式内のtxtからするとipcMain.handle内のtxtは別の変数(グローバル変数のような感じ)と解釈されたのだと思い、main.jsの先頭に``"use strict";``を付けてやってみましたが改善されず。
308
+
309
+ 恐らく**コールバック関数としてのラムダ式が呼ばれる時期が違うため**だと思いますがこれはどのように制御すべきなのでしょうか? それとも呼び出し方が悪いのでしょうか?
310
+
311
+

5

タイトル修正し忘れていたので修正

2022/11/03 06:42

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
@@ -1 +1 @@
1
- eachソッド等に渡すラムダ式内で親の変数使う方法(C++でいうキャプチャのようなもの)
1
+ インプロセス内で取得したデータレンダラープロセスに返す方法
test CHANGED
File without changes

4

markdownがずれていたのを修正

2022/11/03 06:34

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
File without changes
test CHANGED
@@ -297,7 +297,7 @@
297
297
  */
298
298
  ```
299
299
 
300
- 多分、ラムダ式内では別の変数として扱われ、allに渡されたラムダ式のスコープから抜けるので``let txt側の値になっているのだと思いますが、allの外にある``let txt``の値を変化させたいのですが…
300
+ 多分、ラムダ式内では別の変数として扱われ、allに渡されたラムダ式のスコープから抜けるので``let txt``側の値になっているのだと思いますが、allの外にある``let txt``の値を変化させたいのですが…
301
301
  (うまく伝えられなくてすみません)
302
302
 
303
303
 

3

質問の意図を変更した(アドバイスがあったため)

2022/11/03 06:30

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
File without changes
test CHANGED
@@ -6,7 +6,8 @@
6
6
  ### 実現したいこと
7
7
 
8
8
  - [ ] (最終的には)let txtの値を最終的に呼び出し側に相当するrenderer.jsに返したい
9
+ - [ ] 双方向にやり取りをするにはinvokeとhandleを使って行うのはわかっているが、なぜかmain.jsから送れない(ため、その問題を解決したい)
9
- - [ ] C++でいう[ラムダ式](https://cpprefjp.github.io/lang/cpp11/lambda_expressions.html)で用いるキャプチャのような機能はどのようにすべきか
10
+ ~~- [ ] C++でいう[ラムダ式](https://cpprefjp.github.io/lang/cpp11/lambda_expressions.html)で用いるキャプチャのような機能はどのようにすべきか~~
10
11
 
11
12
 
12
13
  今までJavaScriptは触っても(ループ系は)for文ぐらいしかやっていなかったので戸惑っています。
@@ -23,7 +24,8 @@
23
24
  ```
24
25
  のような感じで一つの文字列にしたいです。(最終的に使うものは配列でOKですが)
25
26
 
26
- ここで問題になるのはallメソッドに渡されたラムダ式からすると外部変数(?)にあたるtxtに値を追加したいということです。C++だと キャプチャを使って``auto f = [&a] { return a; };``のように使えますが、JavaScript(or node.js)ではこの処理はできないのでしょうか?
27
+ ここで問題になるのはallメソッドに渡されたラムダ式からすると外部変数(?)にあたるtxtに値を追加したいということです。~~C++だと キャプチャを使って``auto f = [&a] { return a; };``のように使えますが、JavaScript(or node.js)ではこの処理はできないのでしょうか?~~
28
+ キャプチャはできているようなので、それを呼び出し側であるrenderer.jsに返したいのですが、恐らく下の追記1のコードではallメソッド内のtxtとその親の関数内のtxtは別のものと認識されているため、空で返されます。
27
29
 
28
30
  ### 該当のソースコード
29
31
 

2

追記1

2022/11/03 05:10

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
File without changes
test CHANGED
@@ -5,7 +5,9 @@
5
5
 
6
6
  ### 実現したいこと
7
7
 
8
+ - [ ] (最終的には)let txtの値を最終的に呼び出し側に相当するrenderer.jsに返したい
8
- - [ ] C++でいう[ラムダ式](https://cpprefjp.github.io/lang/cpp11/lambda_expressions.html)で用いるキャプチャのような機能はどのようにすべきか
9
+ - [ ] C++でいう[ラムダ式](https://cpprefjp.github.io/lang/cpp11/lambda_expressions.html)で用いるキャプチャのような機能はどのようにすべきか
10
+
9
11
 
10
12
  今までJavaScriptは触っても(ループ系は)for文ぐらいしかやっていなかったので戸惑っています。
11
13
 
@@ -268,3 +270,34 @@
268
270
  言語: JavaScript
269
271
  node.js : node v16.17.0
270
272
  Electron: Electron v21.1.1
273
+
274
+ ----------------
275
+
276
+ [追記1]
277
+
278
+ su507さんがご提示してくださったようにconsole.logをallメソッド内の処理として移動させると確かに表示されますが、最終的には呼び出し側に相当するrenderer.jsにtxtの値を渡したいのです。
279
+
280
+ ```
281
+ // やったこと4
282
+
283
+ let txt = "";
284
+ db.all("select * from users", (error, rows) =>{
285
+ rows.forEach(row => { txt += "hello"; });
286
+ console.log( "select = " + txt ); // ①
287
+ });
288
+
289
+ // ②
290
+ return txt;
291
+
292
+ /*
293
+ 結果:
294
+ 確かに ①で"select = hellohello" と表示されるが、できれば②でrenderer.jsに返したい。
295
+ */
296
+ ```
297
+
298
+ 多分、ラムダ式内では別の変数として扱われ、allに渡されたラムダ式のスコープから抜けるので``let txt側の値になっているのだと思いますが、allの外にある``let txt``の値を変化させたいのですが…
299
+ (うまく伝えられなくてすみません)
300
+
301
+
302
+
303
+

1

言語名の追加

2022/11/03 03:59

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
File without changes
test CHANGED
@@ -265,5 +265,6 @@
265
265
 
266
266
  ### 補足情報(FW/ツールのバージョンなど)
267
267
 
268
+ 言語: JavaScript
268
269
  node.js : node v16.17.0
269
270
  Electron: Electron v21.1.1