質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

313閲覧

Node.jsで非同期処理を実行するとthisの中身が消える

Praline

総合スコア46

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2018/02/01 16:06

前提・実現したいこと

サーバ上のログファイルを読込み、行ごとに処理を分岐させながらインスタンスの生成と値を設定したい。
ログは"-"で始まる区切り行と、それ以外のログ情報を持った行を持つ。

該当のソースコード

javascript

1const LogObj = require("./LogObj.js"); //自作モジュール 2 3module.exports = class LogReader{ 4 constructor(path){ 5 6 var fs = require("fs"); 7 var rs = fs.createReadStream("log.txt"); 8 var readline = require("readline"); 9 var rl = readline.createInterface(rs, {}); 10 11 rl.on("line", function(line) { 12 if( line.substr(0,1) == "-" ){ //ログは行頭が"-"の区切り行で1つのブロック 13 this.tmp.hoge(); //何かしら処理を行ったあと 14 this.tmp = new LogObj(); //インスタンスを再生成[※1] 15 }else{ 16 this.tmp.setlog(line); //ログの中身を追加するメソッド 17 } 18 }).on("close", function(){ 19 this.tmp.hoge(); //最後のセクションの処理 20 }) 21 } 22}

発生している問題・エラーメッセージ

最初のthis.tmp.setlog(line)実行時、setlogが未定義となる。

試したこと

[※1]行直後にthis.tmp.setlog("test")などを挟むと問題なく実行できているので、LogObj側の定義は問題ないはず。
コールバック関数内での処理なので、on内で定義したthis.tmpが処理後には空になる点は認識している。
しかしonで繰り返しループ処理を行っている間も保持されないのか?

本来はthis.tmpを配列にして次々オブジェクトをループの中でpushしたかったのですが、上記の通りonが非同期関数かつコールバック関数内ということもあり、他言語のように同期的な処理の書き方がわからず困っております。

難しければ、モジュール先頭にグローバル変数のようなものを置いて処理すべきなのかなとも思っております。
ただthisじゃないのがなんとなく美しくないなと…

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

functionを使うと、thisは外側のthis変化してしまいます。アロー関数(() => {...}の形)で書きましょう。

あと、

他言語のように同期的な処理の書き方がわからず困っております。

こちらについては、Node.jsの7.6以上であればネイティブでasync awaitが使えるようになっています。

投稿2018/02/01 22:30

maisumakun

総合スコア145201

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Praline

2018/02/03 14:18

ありがとうございます。先にご回答いただけたのでBAにさせていただきました。 取り急ぎ未定義が出ることがなくなりました。
guest

0

Function.bindでコールバック関数内の変数thisをコンストラクタ内のthisに束縛する方法もあります.

参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind


こんな感じ?

JavaScript

1const LogObj = require("./LogObj.js"); //自作モジュール 2 3module.exports = class LogReader{ 4 constructor(path){ 5 6 var fs = require("fs"); 7 var rs = fs.createReadStream("log.txt"); 8 var readline = require("readline"); 9 var rl = readline.createInterface(rs, {}); 10 11 rl.on("line", function(line) { 12 if( line.substr(0,1) == "-" ){ //ログは行頭が"-"の区切り行で1つのブロック 13 this.tmp.hoge(); //何かしら処理を行ったあと 14 this.tmp = new LogObj(); //インスタンスを再生成[※1] 15 }else{ 16 this.tmp.setlog(line); //ログの中身を追加するメソッド 17 } 18 }.bind(this)/*←ここ*/).on("close", function(){ 19 this.tmp.hoge(); //最後のセクションの処理 20 }.bind(this)/*←ここ*/) 21 } 22}

NOTE:
bindの引数を修正しました.

投稿2018/02/02 00:58

編集2018/02/02 01:10
defghi1977

総合スコア4756

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2018/02/02 01:00

コンストラクタ内部ということで、thisはrlではなくて、現在のインスタンスを取りたいのではないかと思うのですが…どうでしょうか。
defghi1977

2018/02/02 01:02

脊髄反射で書いてしまったけれど, コンストラクタ内部まで見てませんでした.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問