zoukankan      html  css  js  c++  java
  • 完全基于node的web应用

    完全基于node的web应用

     

     

    事实上通常“正确的方式”一般都不简单。

    这其中涉及了nodejs中服务端JavaScript,函数式编程,阻塞与非阻塞,回调,事件,内部和外部模块等问题,但是函数式编程,阻塞与非阻塞,回调,事件这些编程思想是通用的,值得学习。
    Node入门

    用例

    • 用户可以通过浏览器使用我们的应用。

    • 当用户请求http://domain/start时,可以看到一个欢迎页面,页面上有一个文件上传的表单。

    • 用户可以选择一个图片并提交表单,随后文件将被上传到http://domain/upload,该页面完成上传后会把图片显示在页面上。

    模块

    • 提供一个web页面,需要http服务器

    • 需要一个路由处理URL请求,对应到请求处理程序(requet handle)。

    • 路由处理POST数据,把数据封装好后传递给请求处理程序。

    • 最终的请求处理程序。

    • 返回一个对应视图给浏览器。

    • 上传功能。

    基本http服务器

    • server.js

      1. var http = require ("http"); 
      2. http.createServer(function (request,response)
      3. response.writeHead(200,{"Content-Type":"text/plain"}); 
      4. response.write("hello world"); 
      5. response.end(); 
      6. }).listen(8888); 

    基于事件驱动回调

    • server.js

    1. var http = require("http"); 
    2.  
    3. //这是一个事件回调函数 
    4. function onRequest(request, response)
    5. console.log("Request received."); 
    6. response.writeHead(200, {"Content-Type": "text/plain"}); 
    7. response.write("Hello World"); 
    8. response.end(); 

    9. //一旦由请求事件,onRequest函数被调用 
    10. http.createServer(onRequest).listen(8888); 
    11.  
    12. console.log("Server has started."); 

    模块化server

    • server.js

      1. var http = require("http"); 
      2.  
      3. function start()
      4. function onRequest(request, response)
      5. console.log("Request received."); 
      6. response.writeHead(200, {"Content-Type": "text/plain"}); 
      7. response.write("Hello World"); 
      8. response.end(); 

      9.  
      10. http.createServer(onRequest).listen(8888); 
      11. console.log("Server has started."); 

      12. //导出函数 
      13. exports.start = start; 

    路由模块,依赖注入到service

    • router.js

      1. function route(pathname)
      2. console.log("About to route a request for " + pathname); 

      3.  
      4. exports.route = route; 
    • server.js

      1. var http = require("http"); 
      2. var url = require("url"); 
      3.  
      4. function start(route)
      5. function onRequest(request, response)
      6. var pathname = url.parse(request.url).pathname; 
      7. console.log("Request for " + pathname + " received."); 
      8.  
      9. route(pathname);//依赖注入 
      10.  
      11. response.writeHead(200, {"Content-Type": "text/plain"}); 
      12. response.write("Hello World"); 
      13. response.end(); 

      14.  
      15. http.createServer(onRequest).listen(8888); 
      16. console.log("Server has started."); 

      17.  
      18. exports.start = start; 
    • index.js

      1.  
      2. var server = require("./server"); 
      3. var router = require("./router"); 
      4.  
      5. server.start(router.route);//依赖注入 

    行为驱动处理函数,函数式编程

    • requestHandlers.js

      1. //行为实现 
      2. function start()
      3. console.log("Request handler 'start' was called."); 
      4. return "Hello Start"

      5.  
      6. function upload()
      7. console.log("Request handler 'upload' was called."); 
      8. return "Hello Upload"

      9.  
      10. exports.start = start; 
      11. exports.upload = upload; 
    • index.js

      1. var server = require("./server"); 
      2. var router = require("./router"); 
      3. var requestHandlers = require("./requestHandlers"); 
      4.  
      5. var handle = {}//根据路由执行行为定义 
      6. handle["/"] = requestHandlers.start; 
      7. handle["/start"] = requestHandlers.start; 
      8. handle["/upload"] = requestHandlers.upload; 
      9.  
      10. server.start(router.route, handle); 
    • server.js

      1. var http = require("http"); 
      2. var url = require("url"); 
      3.  
      4. function start(route, handle)
      5. function onRequest(request, response)
      6. var pathname = url.parse(request.url).pathname; 
      7. console.log("Request for " + pathname + " received."); 
      8.  
      9. response.writeHead(200, {"Content-Type": "text/plain"}); 
      10. var content = route(handle, pathname) //路由行为分配 
      11. response.write(content); 
      12. response.end(); 

      13. http.createServer(onRequest).listen(8888); 
      14. console.log("Server has started."); 

      15.  
      16. exports.start = start; 
    • router.js

      1. function route(handle, pathname)
      2. console.log("About to route a request for " + pathname); 
      3. //根据路由分配行为 
      4. if (typeof handle[pathname] === 'function') { 
      5. return handle[pathname](); 
      6. } else
      7. console.log("No request handler found for " + pathname); 
      8. return "404 Not found"


      9.  
      10. exports.route = route; 

    阻塞与非阻塞

    nodeJS它通过事件轮询(event loop)来实现并行操作,所以尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。
    要用非阻塞操作,我们需要使用回调。
    回调就是:你继续处理你的事情,我(Node.js线程)先不等你了,我继续去处理你后面的代码,请你提供一个callbackFunction(),等你处理完之后我会去调用该回调函数的,谢谢!

    阻塞的请求

    • requestHandlers.js

    1. function start()
    2. console.log("Request handler 'start' was called."); 
    3.  
    4. function sleep(milliSeconds)
    5. var startTime = new Date().getTime(); 
    6. while (new Date().getTime() < startTime + milliSeconds); 

    7. sleep(10000); 
    8. return "Hello Start"

    9.  
    10. function upload()
    11. console.log("Request handler 'upload' was called."); 
    12. return "Hello Upload"

    13. exports.start = start; 
    14. exports.upload = upload; 
    15.  

    处理POST请求

    • requestHandlers.js

      1. function start(response)
      2. console.log("Request handler 'start' was called."); 
      3.  
      4. var body = '<html>'
      5. '<head>'
      6. '<meta http-equiv="Content-Type" content="text/html; '
      7. 'charset=UTF-8" />'
      8. '</head>'
      9. '<body>'
      10. '<form action="/upload" method="post">'
      11. '<textarea name="text" rows="20" cols="60"></textarea>'
      12. '<input type="submit" value="Submit text" />'
      13. '</form>'
      14. '</body>'
      15. '</html>'
      16.  
      17. response.writeHead(200, {"Content-Type": "text/html"}); 
      18. response.write(body); 
      19. response.end(); 

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

      26.  
      27. exports.start = start; 
      28. exports.upload = upload; 

    request监听器

    • server.js

      1. var http = require("http"); 
      2. var url = require("url"); 
      3.  
      4. function start(route, handle)
      5. function onRequest(request, response)
      6. var postData = "";//传输的数据 
      7. var pathname = url.parse(request.url).pathname; 
      8. console.log("Request for " + pathname + " received."); 
      9.  
      10. request.setEncoding("utf8"); 
      11. //监听数据传输 
      12. request.addListener("data", function(postDataChunk)
      13. postData += postDataChunk; 
      14. console.log("Received POST data chunk '"
      15. postDataChunk + "'."); 
      16. }); 
      17. //传输结束一次处理 
      18. request.addListener("end", function()
      19. route(handle, pathname, response, postData); 
      20. }); 
      21.  

      22.  
      23. http.createServer(onRequest).listen(8888); 
      24. console.log("Server has started."); 

      25.  
      26. exports.start = start; 

    数据传输给路由

    • router.js

      1. function route(handle, pathname, response, postData)
      2. console.log("About to route a request for " + pathname); 
      3. if (typeof handle[pathname] === 'function') { 
      4. handle[pathname](response, postData); 
      5. } else
      6. console.log("No request handler found for " + pathname); 
      7. response.writeHead(404, {"Content-Type": "text/plain"}); 
      8. response.write("404 Not found"); 
      9. response.end(); 


      10.  
      11. exports.route = route; 

    响应请求

    • requestHandlers.js

      1. var querystring = require("querystring"); 
      2.  
      3. function start(response, postData)
      4. console.log("Request handler 'start' was called."); 
      5.  
      6. var body = '<html>'
      7. '<head>'
      8. '<meta http-equiv="Content-Type" content="text/html; '
      9. 'charset=UTF-8" />'
      10. '</head>'
      11. '<body>'
      12. '<form action="/upload" method="post">'
      13. '<textarea name="text" rows="20" cols="60"></textarea>'
      14. '<input type="submit" value="Submit text" />'
      15. '</form>'
      16. '</body>'
      17. '</html>'
      18.  
      19. response.writeHead(200, {"Content-Type": "text/html"}); 
      20. response.write(body); 
      21. response.end(); 

      22. function upload(response, postData)
      23. console.log("Request handler 'upload' was called."); 
      24. response.writeHead(200, {"Content-Type": "text/plain"}); 
      25. response.write("You've sent the text: "
      26. querystring.parse(postData).text); 
      27. response.end(); 

      28.  
      29. exports.start = start; 
      30. exports.upload = upload; 

    使用外部模块上传文件

    node-formidable模块 安装

    npm insatll formidable
    npm install formidable -g express -d

    node-formidable官方的例子

    var formidable = require('formidable'),
        http = require('http'),
        util = require('util');
    
    http.createServer(function(req, res) {
      if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
        // parse a file upload
        var form = new formidable.IncomingForm();
        form.parse(req, function(err, fields, files) {
          res.writeHead(200, {'content-type': 'text/plain'});
          res.write('received upload:
    
    ');
          res.end(util.inspect({fields: fields, files: files}));
        });
        return;
      }
    
      // show a file upload form
      res.writeHead(200, {'content-type': 'text/html'});
      res.end(
        '<form action="/upload" enctype="multipart/form-data" '+
        'method="post">'+
        '<input type="text" name="title"><br>'+
        '<input type="file" name="upload" multiple="multiple"><br>'+
        '<input type="submit" value="Upload">'+
        '</form>'
      );
    }).listen(8888);
    

    读取图片数据

    • requestHandlers.js

      1. var querystring = require("querystring"), 
      2. fs = require("fs"); 
      3.  
      4. function start(response, postData)
      5. console.log("Request handler 'start' was called."); 
      6.  
      7. var body = '<html>'
      8. '<head>'
      9. '<meta http-equiv="Content-Type" '
      10. 'content="text/html; charset=UTF-8" />'
      11. '</head>'
      12. '<body>'
      13. '<form action="/upload" method="post">'
      14. '<textarea name="text" rows="20" cols="60"></textarea>'
      15. '<input type="submit" value="Submit text" />'
      16. '</form>'
      17. '</body>'
      18. '</html>'
      19.  
      20. response.writeHead(200, {"Content-Type": "text/html"}); 
      21. response.write(body); 
      22. response.end(); 

      23.  
      24. function upload(response, postData)
      25. console.log("Request handler 'upload' was called."); 
      26. response.writeHead(200, {"Content-Type": "text/plain"}); 
      27. response.write("You've sent the text: "
      28. querystring.parse(postData).text); 
      29. response.end(); 

      30.  
      31. function show(response, postData)
      32. console.log("Request handler 'show' was called."); 
      33. fs.readFile("/tmp/test.png", "binary", function(error, file)
      34. if(error) { 
      35. response.writeHead(500, {"Content-Type": "text/plain"}); 
      36. response.write(error + " "); 
      37. response.end(); 
      38. } else
      39. response.writeHead(200, {"Content-Type": "image/png"}); 
      40. response.write(file, "binary"); 
      41. response.end(); 

      42. }); 

      43.  
      44. exports.start = start; 
      45. exports.upload = upload; 
      46. exports.show = show; 
    • index.js

      1. var server = require("./server"); 
      2. var router = require("./router"); 
      3. var requestHandlers = require("./requestHandlers"); 
      4.  
      5. var handle = {} 
      6. handle["/"] = requestHandlers.start; 
      7. handle["/start"] = requestHandlers.start; 
      8. handle["/upload"] = requestHandlers.upload; 
      9. handle["/show"] = requestHandlers.show; 
      10.  
      11. server.start(router.route, handle); 

    上传图片

    • requestHandlers.js

      1. var querystring = require("querystring"), 
      2. fs = require("fs"), 
      3. formidable = require("formidable"); 
      4.  
      5. function start(response)
      6. console.log("Request handler 'start' was called."); 
      7.  
      8. var body = '<html>'
      9. '<head>'
      10. '<meta http-equiv="Content-Type" content="text/html; '
      11. 'charset=UTF-8" />'
      12. '</head>'
      13. '<body>'
      14. '<form action="/upload" enctype="multipart/form-data" '
      15. 'method="post">'
      16. '<input type="file" name="upload" multiple="multiple">'
      17. '<input type="submit" value="Upload file" />'
      18. '</form>'
      19. '</body>'
      20. '</html>'
      21.  
      22. response.writeHead(200, {"Content-Type": "text/html"}); 
      23. response.write(body); 
      24. response.end(); 

      25.  
      26. function upload(response, request)
      27. console.log("Request handler 'upload' was called."); 
      28.  
      29. var form = new formidable.IncomingForm(); 
      30. console.log("about to parse"); 
      31. form.parse(request, function(error, fields, files)
      32. console.log("parsing done"); 
      33. fs.renameSync(files.upload.path, "/tmp/test.png"); 
      34. response.writeHead(200, {"Content-Type": "text/html"}); 
      35. response.write("received image:<br/>"); 
      36. response.write("<img src='/show' />"); 
      37. response.end(); 
      38. }); 

      39.  
      40. function show(response)
      41. console.log("Request handler 'show' was called."); 
      42. fs.readFile("/tmp/test.png", "binary", function(error, file)
      43. if(error) { 
      44. response.writeHead(500, {"Content-Type": "text/plain"}); 
      45. response.write(error + " "); 
      46. response.end(); 
      47. } else
      48. response.writeHead(200, {"Content-Type": "image/png"}); 
      49. response.write(file, "binary"); 
      50. response.end(); 

      51. }); 

      52.  
      53. exports.start = start; 
      54. exports.upload = upload; 
      55. exports.show = show; 
    • server.js

      1. var http = require("http"); 
      2. var url = require("url"); 
      3.  
      4. function start(route, handle)
      5. function onRequest(request, response)
      6. var pathname = url.parse(request.url).pathname; 
      7. console.log("Request for " + pathname + " received."); 
      8. route(handle, pathname, response, request); 

      9.  
      10. http.createServer(onRequest).listen(8888); 
      11. console.log("Server has started."); 

      12.  
      13. exports.start = start; 

    fs模块的问题 文件路径问题

    1. function upload(response,request)
    2. console.log("Request handler 'upload' was called"); 
    3. // response.writeHead(200, { 
    4. // "Content-Type": "text/plain" 
    5. // }); 
    6. // response.write("you are sent: " + querystring.parse(postData).text); 
    7. // response.end(); 
    8. // response.write("hello upload"); 
    9. //return "hello upload"; 
    10. // 
    11. //文件上传 
    12. var form =new formidable.IncomingForm(); 
    13. console.log("start to parse"); 
    14. form.uploadDir = "tem"
    15. form.parse(request,function(error,fields,files)
    16. console.log("parsing done"); 
    17. try
    18. fs.renameSync(files.upload.path,form.uploadDir+"/test.png");//主要修改了这个地方 
    19. }catch(e){ 
    20. console.log(e); 

    21.  
    22. response.writeHead(200,{"Content-Type":"text/html"}); 
    23. response.write("received image:<br/>"); 
    24. response.write("<img src='/show'>"); 
    25. response.end(); 
    26. }) 

    只要心中有梦,不管什么天气都适合睡觉
  • 相关阅读:
    python 实现单链表
    java解压缩zip
    关于 ElesticSearch 安装
    spring boot 与 spring cloud 关系
    Java并发编程:深入剖析ThreadLocal
    mybatis like 的坑
    JMeter 压力测试使用CSV参数
    IntelliJ IDEA创建多模块依赖项目
    关于IntelliJ IDEA删除项目
    switchhost -- 切换host的工具
  • 原文地址:https://www.cnblogs.com/mmry/p/6262238.html
Copyright © 2011-2022 走看看