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

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

ただいまの
回答率

88.33%

fs.existsは非推奨なのでs.statまたは、fs.accessで、実行したい。

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 4,550

takusabuwp

score 13

前提・実現したいこと

javascript,node.jsの基本をかじって分かったつもりの初心者です。

### Node.jsで、serverを使って、指定フォルダ内のHTML、CSS、JAVASCRIPTをブラウザに表示させたい。

前提にcontentフォルダを作成
その中にhtml、css、JavaScriptファイルを作成。 

実現したいこと
fs.existsは非推奨なのでs.statまたは、fs.accessで、実行したい。

fs.existsやexistの部分をstatまたは、accessに変更しただけでは、実装中に以下のエラーメッセージが発生。

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

ページが見つかりません! 

該当のソースコード

server.js

var http = require('http');
var path = require('path');
var fs = require('fs');

var mimeTypes = {
    '.js': 'text/javascript',
    '.html': 'text/html',
    '.css': 'text/css'
};

http.createServer(function (request, response) {
    var lookup = path.basename(decodeURI(request.url)) || 'index.html',
    f = 'content/' + lookup;
    fs.exists(f, function (exists) {
        if (exists) {
            fs.readFile(f, function(err, data) {
                if (err) {
                    response.writeHead(500);
                    response.end('Server Error!');
                    return;
                }
                var headers = {'Content-Type': mimeTypes[path.extname(f)] + ';charset=utf-8'};
                response.writeHead(200, headers);
                response.end(data);
            });
            return;
        }
        response.writeHead(404);
        response.end('ページがみつかりません!');
    });
}).listen(8080);

試したこと

参考サイトをまねして例外処理を適用してみたが、変化なし。

https://www.tech-tech.xyz/nodejs-writefile-mkdir-stat-access.html#fsstatfsaccess

補足情報(FW/ツールのバージョンなど)

node v10.15.0
npm  4.0.5

ソースコード元:

oreilly 「Nodeクックブック」

レシピ 1.1 URL ルーティングを設定する

https://www.amazon.co.jp/dp/4873116066?_encoding=UTF8&isInIframe=0&n=465392&ref_=dp_proddesc_0&s=books&showDetailProductDesc=1#product-description_feature_div

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

こちらにありますように、fs.existsには競合状態(存在チェックの直後にファイルの作成・削除などが行われると想定どおりに進まない)問題があります。

Using fs.exists() to check for the existence of a file before calling fs.open(), fs.readFile() or fs.writeFile() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file does not exist. (Node.jsドキュメントより)

fs.existsでのチェックを行わずにfs.readFileを行って、errorの際にerror.codeを見てファイルが存在しない(ENOENT)かそれ以外のエラー化を確認するようにしましょう。

エラーコードの一覧

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/28 09:35

    つまり、ファイルがあるかを事前にチェックすること「そのもの」がよくない、ということです。

    キャンセル

  • 2019/02/28 09:59 編集

    maisumakunさん、早速のアドバイスありがとうございます。

    むむむ、If文内、全体を変えないといけなさそうですね。
    まだまだ、勉強が必要なようです。
    参考サイトや参考資料が、あれば教えていただけませんか
    ?英文は苦手なので、日本語がいいですが、、、

    キャンセル

  • 2019/02/28 11:00 編集

    so87さん、これは、回答ですね。
    ヒントをもとに問いてないのに回答をもらってしまって恐縮です。
    新しい、命令語が続々と、、、
    勉強になります。

    キャンセル

+1

なぜfs.existsが非推奨になったのか知る必要があります。
そしてfs.exists 非推奨でググれば、すぐに知れます。
その内容はmaisumakunさんの回答のとおりなのですが、じゃあどうすれば?ということですよね。
初心者さんということで、足がかりになればと思い、ざっくりリファクタリングしておきます。(わからない時は右も左も知ってるはずなのにわからないですから^^)

const http = require('http')
const path = require('path')
const fs = require('fs')
const util = require('util')

const readFile = util.promisify(fs.readFile)

const mimeTypes = {
    '.js': 'text/javascript',
    '.html': 'text/html',
    '.css': 'text/css',
};

http.createServer(async function (request, response) {
    const lookup = path.basename(decodeURI(request.url)) || 'index.html'
    const filepath = 'content/' + lookup

    try {
        const data = await readFile(filepath)
        const headers = {'Content-Type': mimeTypes[path.extname(filepath)] + ';charset=utf-8'}
        response.writeHead(200, headers)
        response.end(data)
    } catch (err) {
        response.writeHead(404)
        response.end('ページがみつかりません!')
    }

}).listen(8080);

fs.existsした後にfs.readFileは意味ない、ダサいということです。
ファイルを読み込みたいのだから、素直にfs.readFileしちゃえってことです。
あと関係ないですが、node.js v10をご利用ということですので、varは極力避けてconstで書いていく(後々身にしみてvarの気持ち悪さを感じるようになります)。そしてなるべくPromise化を行い、async/await構文を使ってコーディングできるようになると、脱初心者です。
頑張ってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る