Android APP的开发告一段落,一个稳定的、实现了基本功能的APP已经交付用户使用了!我和老板交流了下,接下来准备转战Node.js了,而且一部分前端的功能也要做进去!哈哈哈~~~接下来要朝一个全(zuo)栈(si)工程师进发了,想想都有点小激动呢!这几天一直在学新东西,HTML CSS JavaScript jQuery SQL bootstrap Node.js ···········
  
  (好吧,看着这么多前端+后端的知识,我已经凌乱在风中了-。-·····)
  
  要学的东西是蛮多的,时间又紧,后来我在知乎一番搜索后决定主攻Node.js,SQL等用到时再去查语句怎么写,JavaScript学习基本的语法和关键的一些思想(回调、闭包····)HTML CSS 力求能看懂,jQuery也尝试着写,这里先给大家推荐一个不错的网站,世界上最大学习网站开发的地方 w3schools (简单直白的英文网站,可以锻炼下自己看英文文档的能力,貌似需要FQ,请自备梯子),没有梯子的童鞋可以去 菜鸟教程(中国人自己翻译的网站,内容基本一致),小小的吐槽下:w3schools 的exercise太水了,几道题基本做法都差不多,最多就修改两三个地方,并且学完之后的测试居然就是24道选择题(很多还都是判断题······),还以为很难呢·······不过貌似人家盈利的方式就是最后学完后的certificate,价格是惊人的 95 美刀(在国外知识确实很值钱-。-)
  
  废话不多说,进入正题吧,我是在网上看的这本《Node入门》总共就42页,一边看一边背书里的代码自己写,一天就看完了,还是有不少收获的。
  
  首先咱们要安装Node.js,我用的是Windows版本的安装包,直接下载安装就好,然后大家还需要装一下sublime text 3。下面是我们最终要达到的三个目标。
  
  用户可以通过浏览器使用我们的应用。
  
  当用户请求http://127.0.0.1:8888/start时,可以看到一个欢迎页面,页面上有一个文件上传的表单。
  
  用户可以选择一个图片并提交表单,随后文件将被上传到http://127.0.0.1:8888/upload,该页面完成上传后会把图片显示在页面上。
  
  最后的效果是这样:上传图片的效果
  
  图片上传后的效果
  
  书里有一部分关于直接把函数作为参数进行传值的话我觉得讲的很好,现在摘录出来方便大家理解下什么是 函数式编程
  
  行为驱动执行
  
  请允许我再次脱离主题,在这里谈一谈函数式编程。
  
  将函数作为参数传递并不仅仅出于技术上的考量。对软件设计来说,这其实是个哲学问题。想想这样的场景:在index文件中,我们可以将router对象传递进去,服务器随后可以调用这个对象的route函数。
  
  就像这样,我们传递一个东西,然后服务器利用这个东西来完成一些事。嗨那个叫路由的东西,能帮我把这个路由一下吗?
  
  但是服务器其实不需要这样的东西。它只需要把事情做完就行,其实为了把事情做完,你根本不需要东西,你需要的是动作。也就是说,你不需要名词,你需要动词。
  
  理解了这个概念里最核心、最基本的思想转换后,我自然而然地理解了函数编程。
  
  关于Node.js还有一点需要理解的是阻塞IO与非阻塞IO(使用回调函数)的不同
  
  简单来说,假设我们要去快餐店吃饭,有两种不同服务模式的快餐店,一种是基于事件驱动的(我们的node服务器),一种不是(像iis,apache)。对于传统的服务器,在接收到你的请求之后,直到他完成你的请求,否则他不会去接待下一个用户。当服务员输入你的订单之后还有很多事情要做,处理你的支付,帮你倒水,还有一段时间(不确定时长)去等待厨房准备好你的汉堡。服务员(相当于服务器上的线程)每次只能接待一位顾客,直到完成当前顾客的接待之后,才会去接待下一位顾客。很显然,这种方式效率不高,他浪费了太多的时间在等待厨房做汉堡的工作上。而现实中的快餐店采用的是另外一种模式,当接收到你的订单之后,他会给你一个号码牌,这个号码牌就相当于回调函数。接着他会去接待下一位顾客。当你的订餐准备好之后,服务员会呼叫你的号码叫你来取餐。这就是node采用的模式,看得出他要高效的多。
  
  一路看着书往下写,我们把这个小Node.js程序分成了三个主要的模块:server(服务器)、router(分发处理不同的请求)、requestHandle(真正处理请求的部分),剩下的就是细节的完善。
  
  最后贴上全部的源码来供大家学习吧,windows下有一个坑,那个坑花了我两个小时才找到,具体见代码·····
  
  主页文件index.js
  
  var server = require('./server'); //本地写的server.js 文件
  
  var router = require('./router');
  
  var requestHandle = require('./requestHandle');
  
  var handle = {};
  
  handle["/"] = requestHandle.start;
  
  handle['/start'] = requestHandle.start;
  
  handle['/upload'] = requestHandle.upload;
  
  handle['/directory'] = requestHandle.directory;
  
  handle['/display'] = requestHandle.display;
  
  server.start(router.route,handle);
  
  server.js
  
  //调用node.js的自带模块http,并将其返回值赋值给 var http
  
  var http = require("http");
  
  var url = require("url");
  
  function start(route, handle) {
  
  //用onRequest作为回调函数
  
  function onRequest(request, response) {
  
  var pathName = url.parse(request.url).pathname;
  
  var postDate = "";
  
  console.log("Request for " + pathName + " has received.");
  
  route(pathName,handle,response,request);
  
  };
  
  http.createServer(onRequest).listen(8888);
  
  console.log("server www.hjha178.com has start");
  
  }
  
  exports.start = start;
  
  router.js
  
  function route(pathName,handle,response,request){
  
  console.log("start router with handle and path name is " + pathName);
  
  if (typeof handle[pathName] === "function") www.furggw.com{
  
  return handle[pathName](response,request); //Node.js中这个执行的方法太酷了
  
  }else{
  
  console.log("404 not find "www.dashugw.com);
  
  response.writeHead(404,{"Content-Type":"text/plain"});
  
  response.write("404 not found");
  
  response.end();
  
  }
  
  }
  
  exports.route = route;
  
  requestHandle.js
  
  var exec = require('child_process').exec;
  
  var queryString = require('querystring');
  
  var fs = require('fs'www.567860.cn);
  
  var formidable = require('formidable');
  
  function start(response) {
  
  console.log("handler 'start' www.272345.cn was called");
  
  //仅仅是为了学习才这么把html写这里的,实际中是绝不能这么丑陋地把html直接写在处理程序里的
  
  var body = '<html>' +
  
  '<head>' +
  
  '<meta http-equiv="content-type" content="text/html;charset=UTF-8">' +
  
  '</head>' +
  
  '<body>' +
  
  //定义submit后的跳转的url是/upload,且是一个post请求
  
  '<form action="/upload" method="post" enctype = "multipart/form-data">' +
  
  '<input type="file" name="upload" multiple="multiple" ><br/>' +
  
  '<input type="submit" value="upload file">' +
  
  '</form>' +
  
  '</body>' +
  
  '</html>';
  
  response.writeHead(200, {
  
  "Content-Type": "text/html"
  
  });
  
  response.write(body);
  
  response.end();
  
  }
  
  function upload(response, request) {
  
  console.log("handler 'upload' was called");
  
  var form = new formidable.IncomingForm();
  
  //关键:这里需要改变form的默认的上传路径,且在windows下由于权限的问题,需要手动创建tmp文件夹
  
  form.uploadDir = 'tmp';
  
  form.parse(request, www.taohuayuan178.com function(error, fields, files) {
  
  console.log(files.upload.path);
  
  // fs.renameSync(files.upload.path, "/tmp/test.png");
  
  //考虑到这个是Sync同步操作,则必须对异常进行捕获,Node.js不推荐同步操作
  
  try{
  
  fs.renameSync(files.upload.path,'tmp/test.png');
  
  }catch(e){
  
  console.log(e);
  
  }
  
  response.writeHead(200, {
  
  "Content-Type": "text/html"
  
  });
  
  response.write('<img src="/display"/>');
  
  response.end();
  
  });
  
  }
  
  function display(response) {
  
  console.log("handler 'display' was called");
  
  fs.readFile("tmp/test.png",function(error, file) {
  
  if (error) {
  
  console.log("sorry");
  
  } else {
  
  response.writeHead(200,{"Content-Type":"image/png"});
  
  // response.write(data);
  
  response.write(file);
  
  response.end();
  
  };
  
  });
  
  }
  
  /*//响应用户输入的display方法
  
  function display(response,postDate) {
  
  console.log("handler 'display' was called");
  
  response.writeHead(200, {
  
  "Content-Type": "text/plain"
  
  });
  
  response.write("You input " + queryString.parse(postDate).text);
  
  response.end();
  
  }*/
  
  exports.start = start;
  
  exports.upload = upload;
  
  exports.directory = directory;

《Node入门》读书笔记——用Node.js开发一个小应用的更多相关文章

  1. [整理]Node入门 » 一本全面的Node.js教程 - Demo实践所遇到的问题

    花了一个上午看完[转载]Node入门 » 一本全面的Node.js教程 根据里面的Demo自己手动实现过程中还是遇到了些问题,特整理在此. <1>.由于node.msi安装包已经自动添加了 ...

  2. 第三章 Git的入门 - 读书笔记

    Android驱动月考3 第三章 Git的入门 - 读书笔记 对于Github,这是全世界最大的开源平台,你可以把你做的项目在这里开源,把你发现的一些新技术在这里开源,向全世界的开发者们分享,大家都彼 ...

  3. 【转】利用 three.js 开发微信小游戏的尝试

    前言 这是一次利用 three.js 开发微信小游戏的尝试,并不能算作是教程,只能算是一篇笔记吧. 微信 WeChat 6.6.1 开始引入了微信小游戏,初期上线了一批质量相当不错的小游戏.我在查阅各 ...

  4. 用Vue.js开发微信小程序:开源框架mpvue解析

    前言 mpvue 是一款使用 Vue.js 开发微信小程序的前端框架.使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为 H5 和小程序提供了代码复用的能力.如果想将 H5 项目改造为小程 ...

  5. MPVUE - 使用vue.js开发微信小程序

    MPVUE - 使用vue.js开发微信小程序 什么是mpvue? mpvue 是美团点评前端团队开源的一款使用 Vue.js 开发微信小程序的前端框架.框架提供了完整的 Vue.js 开发体验,开发 ...

  6. js实现一个小游戏(飞翔的jj)

    js实现一个小游戏(飞翔的jj) 源代码+素材图片在我的仓库 <!DOCTYPE html> <html lang="en"> <head> & ...

  7. 读书笔记: 深入浅出node.js

    >> 深入浅出node.js node.js是c++编写的js运行环境 浏览器: 渲染引擎 + js引擎 后端的js运行环境 node.js用google v8引擎,同时提供很多系统级的A ...

  8. [转载]Node入门 » 一本全面的Node.js教程

    http://www.nodebeginner.org/index-zh-cn.html 作者: Manuel Kiessling 翻译: goddyzhao & GrayZhang & ...

  9. node入门(二)——gulpfile.js初探

    本文关于gulpfile.js怎么写,利于完成个性化需求.本文开发环境默认已安装node,详情参考<node入门(一)——安装>. 一.安装gulp npm install -g gulp ...

随机推荐

  1. css布局笔记(一)

    布局方式 一列布局 通常固定宽高,用margin:0 auto:居中显示 两列布局 说起两列布局,最常见的就是使用float来实现.float浮动布局的缺点是浮动后会造成文本环绕等效果,以及需要及时清 ...

  2. Unity编辑器扩展chapter1

    Unity编辑器扩展chapter1 unity通过提供EditorScript API 的方式为我们提供了方便强大的编辑器扩展途径.学好这一部分可以使我们学会编写一些工具来提高效率,甚至可以自制一些 ...

  3. 如何选择 .NET Framework目标版本

    如何选择 .NET Framework目标版本 简介 .NET Framework是所有 .NET程序赖以运行的基础. 版本 到目前位置 .NET Framework共出了: .NET Framewo ...

  4. centos 6.5 双网卡 上网 virtualbox nat hostonly

    虚拟机两张网卡:分别调成NAT(eth0)和host only(eht1)模式. nat的网卡不用设置,host only网卡调为(vi /etc/sysconfig/network-scripts/ ...

  5. 01_基于TCP的循环为同一个客户端下载文件的下载器

    原版: TCP分为客户端(client)和服务器(server),每次服务器只能为客户端提供一次的下载服务. 改良版: TCP分为客户端(client)和服务器(server), (1)每次服务器能为 ...

  6. CentOS-6.x系列查看cpu核数

    使用CentOS7.x使用习惯了后用top命令,然后按1就可以查看相关的cpu核心数等相关信息 相关概念: 物理CPU:实际Server中插槽上的CPU个数. 物理cpu数量:可以数不重复的 phys ...

  7. Educational Codeforces Round 16 E. Generate a String dp

    题目链接: http://codeforces.com/problemset/problem/710/E E. Generate a String time limit per test 2 seco ...

  8. HDU 5172 GTY's gay friends 线段树+前缀和+全排列

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5172 bc(中文):http://bestcoder.hdu.edu.cn/contest ...

  9. 第四周作业——C语言自评

    1.你对自己的未来有什么规划?做了哪些准备?以目前的现状来说,希望至少能够掌握专业所要求的基本操作,然后一步步去深入.提升,毕业之后不会灰溜溜的一次次求职失败.目前更多的是利用闲暇时间补回过去老师同学 ...

  10. DPDK报文分类与访问控制

    原创翻译,转载请注明出处. dpdk提供了一个访问控制库,提供了基于一系列分类规则对接收到的报文进行分类的能力.ACL库用来在一系列规则上执行N元组查找,可以实现多个分类和对每个分类查找最佳匹配(最高 ...