質問編集履歴
7
問題自体に不備があったため、質問の意図の変更
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
t
|
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
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
タイトル修正し忘れていたので修正
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
メインプロセス内で取得したデータをレンダラープロセスに返す方法
|
test
CHANGED
File without changes
|
4
markdownがずれていたのを修正
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
質問の意図を変更した(アドバイスがあったため)
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
|
-
|
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
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
言語名の追加
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
|