express.jsの正しい姿勢を開く

4850 ワード

今この年月にまたexpressを討論しても、実は喜ばないです.nodejsはもう新しい技術ではないです.nodejsはまだ成熟していませんが、expressの原作者もすでにnodejsを放棄しました.nodejsのパッケージ管理システム、calback hellなどの問題は多くの人に突っ込まれていますが、広大な熱血青年がnodejsに押し寄せてくるのを阻止できません.nodejsはあまりにも魅力的で、バックエンドのエンジニアに未曾有の「フィードバック」言語を提供しています.同時に広大な先端の開発者のために金色に輝く大きな扉を開けました.サーバー側に開発された大きな扉に向かっていますが、これは卵用ではありません.
前後の手順で解決したい問題は実際には違っています.先端を熟知しているエンジニアがnodejsを使ってバックエンドを簡単にコントロールできると思ったら、あなたの考えが多いとしか言えません.フロントエンドプログラムはブラウザで実行されていますが、一番重要な問題はユーザー体験であり、主な困難はコード対ブラウザの互換性です.バックエンドプログラムはオペレーティングシステムで実行されていますが、解決する主な問題は機能の実現、性能、安定性、拡張性・・・です.フロントエンドとバックエンドのコードをそれぞれ探して比較したら、jsですが、文法が似ている以外には似ているところがありません.
はい、余計な話はしません.express.jsを見に来ました.
哲学について話しましょう.
express.jsで開発者に必要なのは主に何ですか?
まず、公式の例を見てみます.
var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);
expressの中で私達の最も主要な任務はap.get()を実現するので、ap.post()の中のcalback部分、expressの中でroute handlerと言って、つまり通常私達の言ったcontroller.
どうやってrequestに対する処理を開始しますか?
公式文書でこのように書くと言っています.
app.get('/', function(req, res){
  res.send('hello world');
});
app.getの二番目のパラメータは一つのcalbackで、彼は二つのパラメータを受けています.一つはrequestで、一つはreponseです.
しかし、文書をよく見ると、app.getの定義は実はこのようなものです.複数のcalbackがあります.どう使いますか
// app.get    callback            --    callback
//    callback   app.get        route handler(   nodejs)

app.get('/', function(req, res, next){
  //blabla,     1
  //blabla,     1
  //blabla,     1
  next(); //        handler
          //  |
          //  |
          // \|/
}, function(req, res, next){
  //blabla,     2
  //blabla,     2
  //blabla,     2
  next(); //        handler
          //  |
          //  |
          // \|/
}, function(req, res){
  //      handler       next
  //    response
  res.send('hello world');
});
ほとんどの場合、app.get(path, callback [, callback ...])はパラメータが必要ではないが、実際にはパラメータを受け入れることができるので、ここでは2つの場合がある.
  • next()は、後のroute handlerをスキップすることができます.
  • next('route')も後続のroute handlerをスキップしますが、next(err)とは違い、エラー処理をトリガするhandler(後述します).
  • どうやってrequestに対する処理を終えますか?
    簡単に見える問題ではないですか?
    普通はnext('route')を使いますが、高級点はres.end()res.send()res.json()res.links()などを使いますが、これらの関数を呼び出した後で処理は終わりますか?実はないです.res.format()の後のコードはまだ実行されます.
    では、どうやってroute handlerの実行を自発的に終了できますか?答えは上記のres.end()関数ですが、next()の後にコードがあればどうすればいいですか?したがって、一般的な方法は:
    .....
    return next(err);
    //            route handler       .
    .....
    
    エラー処理
    ここではまず、エラー処理に関する公式の指導(英語、中国語)を紹介します.
    expressではグローバルのerror handlerを定義できます.方法は以下の通りです.
    app.use(function(err, req, res, next) {
      console.error(err.stack);
      res.status(500).send('Something broke!');
      // next(err);
    });
    
    error handlerも複数あり得るが、route handlerと同様にnext()を介して直列に接続されており、異なるのは、errパラメータを持つ必要があることである.
    グローバルerror handlerはエンジニアにとても便利なことを提供しましたが、実際のプロジェクトではよく機能しません.原因は一つだけです.
    ここでは実際のプロジェクトの例を要約します.
    exports.client=function(callBack){
        pool.acquire(function(err,db){                          // err       
            var timer=setTimeout(function(){
                pool.release(db);
            },20000);
            db.checkDisconnect=timer;
            callBack(db);
        });
    };
    
    exports.collection=function(db,collectionName,callBack){
        
       db.collection(collectionName,{safe:true},function(err,collection){
           if(err) {                                                       //     err     .
               console.log("DBClient-collection-err: " + err);
           }
          callBack(collection);                                //     callBack(err, collection);
       });
    };
    
    get:function(id,callBack){
        var self=this;
        dbClient.client(function(db){
            dbClient.collection(db,self.DBTable,function(collection){
                collection.findOne({'id':id},function(err, doc){
                    if(err) {                                             //     err     .
                       console.log("DBClient-findOne-err: " + err);
                    }
                    if(doc){
                        delete doc._id; 
                    }
                    
                    callBack(doc);                            //     callBack(err, doc);
                    
                    dbClient.close(db);
                });
            });
        });
    }
    
    
    exports.add=function(req,res){
        var cookie=req.cookies;
        var userid=cookie.userid;
    
        //         dao.findOne         err !!!
        //    err   ,     user          ,          err            err          .        .
        //    err   ,       user      ,        ,             .
    
        dao.findOne({id:userid},config.dbUser,function(user){
            //.....
            //.....