nodejs入门-项目架构

ぃ、小莉子 提交于 2019-12-05 14:14:51

在开始学nodejs时,一般我们就是直接

var http = require("http");
var fs = require('fs')
var url = require('url')
var querystring = require('querystring')
var mysql = require('mysql')


var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : 'root',
  database : 'crashcourse'
})

connection.connect(function(err) {
  if(err) {
    console.log('数据库连接失败')
  }
  console.log('数据库连接成功')
})

http.createServer(function(req,res){
   const pathname = req.url
   if(pathname === '/') {
     fs.readFile('../page/index.html','utf-8',function(err,data) {
       if(err) {
         throw err
       }
       res.writeHead(200,{"Content-type":"text/html"});
       res.write(data)
       res.end()
     })
   }else if(pathname === '/login') {
      var body = ''
      req.on('data',function(chunk) {
        body += chunk
      })
      req.on('end',function() {
        body = querystring.parse(body)  //该方法会把一个 URL 查询字符串 str 解析成一个键值对的集合。

        const sql = 'SELECT * FROM users WHERE username="'+ body.username +'"AND password="'+ body.password+'";'
        connection.query(sql,function(err,results) {
          if(err) {
            throw err
          }

          if(results.length >= 1) {
            const date = new Date().getTime() + 1000
            res.writeHead(200,{"Content-type":"text/plain;charset=utf-8","Set-Cookie":"username="+ body.username+""});
            res.write('登陆成功')
            res.end()
          }else {
            res.writeHead(301,{"Content-type":"text/html;charset=utf8"});
            res.write('<p>登陆失败,用户名或密码错误<a href="/">返回</a></p>')
            res.end()
          }

        })

        // if(body.username ==='admin@qq.com' && body.password === '123') {
        //   res.writeHead(200,{"Content-type":"text/plain;charset=utf-8"});
        //   res.write('登陆成功')
        //   res.end()
        // }else {
        //   res.writeHead(301,{"Content-type":"text/plain;charset=utf-8"});
        //   res.write('用户名密码错误')
        //   res.end()
        // }
      })
   }else if(pathname === '/register') {
       if(req.method === 'POST') {
          var body = ''
          req.on('data',function(chunk) {
            body+=chunk
          })
          req.on('end',function() {
            body = querystring.parse(body)
            if(body.username !== '' && body.password !== '') {
              //方法一  sql语句拼接变量  ?为占位符

               // var addsqlparams = [body.username,body.password];
               // var sql = 'INSERT INTO users VALUES(NULL,?,?);'
               // connection.query(sql, addsqlparams ,function(err,results) {
               //    connection.destroy()
               //    res.writeHead(200,{'content-type': 'text/html;charset=utf8'})
               //    res.write('<p><span>注册成功!</span><a href="/">前往登陆</a></p>')
               //    res.end()
               //    if(err) throw err
               // })

              //方法二
               connection.query('INSERT INTO users VALUES(NULL,"'+ body.username +'","'+ body.password +'")' ,function(err,results) {
                  connection.destroy()
                  res.writeHead(200,{'content-type': 'text/html;charset=utf8'})
                  res.write('<p><span>注册成功!</span><a href="/">前往登陆</a></p>')
                  res.end()
                  if(err) throw err
               })

            }
          })

       }else {
         res.writeHead(200,{"Content-type":"text/html"});
         fs.readFile('../page/register.html',function(err,data) {
           if(err) {
             throw err
           }
           res.write(data)
           res.end()
         })

       }

   }

}).listen(8080);

比如上面这段代码,就是实现一个登陆注册的简单功能,虽然功能是正常实现了,但是代码结构很乱,没有路由来管理请求

我们应该有

  • server 服务器
  • route  路由
  • requestHandlers 请求对应的处理程序
  • model  数据库处理
  • index   入口文件

接下来来改造上面的代码

> server.js

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    //依赖注入
    route(handle, pathname, response,request);
  }

  http.createServer(onRequest).listen(8080);
  console.log("Server has started.");
}

exports.start = start;

router.js

 

function route(handle, pathname, response, request) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    //将response也作为参数传递,以非阻塞操作进行请求响应
    return handle[pathname](response,request);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;

requestHandlers

 

var exec = require("child_process").exec;
var user = require('./model/user');
var fs = require('fs');
var querystring = require('querystring')


function start(response, request) {
  console.log("Request handler 'start' was called.");

  // function sleep(milliSeconds) {
  //   var startTime = new Date().getTime();
  //   while (new Date().getTime() < startTime + milliSeconds);
  // }
  //
  // sleep(10000);

  // var content = "empty";
  // child_process。之所以用它,是为了实现一个既简单又实用的非阻塞操作:exec()
  // exec("ls -lah", function (error, stdout, stderr) {
  //  content = stdout;  //这里是异步操作
  // });
  //
  // return content

  // exec("find /",
  //     { timeout: 10000, maxBuffer: 20000*1024 },
  //     function (error, stdout, stderr) {
  //       response.writeHead(200, {"Content-Type": "text/plain"});
  //       response.write(stdout);
  //       response.end();
  //     });

  if (request.method === 'GET') {
    fs.readFile('../page/index.html', 'utf-8', function(err, data) {
      if (err) {
        throw err
      }
      response.writeHead(200, {
        "Content-type": "text/html"
      });
      response.write(data)
      response.end()
    })
  } else if (request.method === 'POST') {
    var body = ''
    request.on('data', function(chunk) {
      body += chunk
    })
    request.on('end', function() {
      body = querystring.parse(body)

      const sql = 'SELECT * FROM users WHERE username="' + body.username + '"AND password="' + body.password + '";'
      user.query(sql, function(results) {
        if (results.length >= 1) {
          const date = new Date().getTime() + 1000
          response.writeHead(200, {
            "Content-type": "text/plain;charset=utf-8",
            "Set-Cookie": "username=" + body.username + ""
          });
          response.write('登陆成功')
          response.end()
        } else {
          response.writeHead(301, {
            "Content-type": "text/html;charset=utf8"
          });
          response.write('<p>登陆失败,用户名或密码错误<a href="/">返回</a></p>')
          response.end()
        }
      })

    })
  }



}

function upload(response) {
  ///upload URL居然也花了10秒,而它在对应的请求处理程序中并没有类似于sleep()这样的操作!
  // console.log("Request handler 'upload' was called.");
  // return "Hello Upload";

  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {
    "Content-Type": "text/plain"
  });
  response.write("Hello Upload");
  response.end();
}

exports.start = start;
exports.upload = upload;

model.js

var mysql = require('mysql');

var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'root',
  database: 'crashcourse'
})

connection.connect(function(err) {
  if (err) {
    console.log('数据库连接失败')
  }
  console.log('数据库连接成功')
})

function query(sql, callback) {
  connection.query(sql, function(err, results) {
    if (err) throw err
     callback(results)
  })
}

exports.query = query

index.js

var server = require('./server')
var router = require('./router')
var requestHandlers = require('./requestHandlers')

var handle = {}
handle["/"] = requestHandlers.start
handle["/start"] = requestHandlers.start
handle["/upload"] = requestHandlers.upload

server.start(router.route,handle)

在index.js文件中可以看到,将router路由文件和请求处理requestHandlers分别注入到server中,这里新建了一个handle对象,Key值为对应请求的url路径,value为我们在requestHandlers中定义的函数,根据路径的不同分别去调用不同的函数来响应这个请求。

server.js只负责创建服务器,请求分发处理都交给路由来统一管理

在router.js中`typeof handle[pathname] === 'function'` 如果条件成立,代表当前请求有对应的函数来处理。

在server.js将request和response参数传递到requestHandler中,因为要用到这两个对象,比如这里根据req的method如果是GET直接就返回一个html表单界面,是POST代表正在登录。

model里就是随便简单的封装了一下,也可以直接把sql封装到model中,调用的时候不直接写sql语句,而且根据传的值在model中生成,对于一些异步处理可以直接采用Promise等一些方法来处理,以及可以用数据库连接池来处理连接。

可以去参考一下nodejs入门这本书,以后开发的时候肯定直接就用express或koa这种框架来写,但是刚学nodejs时这种简单的架构还是有必要了解一下,对以后学习nodejs相关的web框架肯定是有帮助的。

 

`

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!