learnyounode第13课总结(下)休息前的时间比较忙,所以learnyounode后半部分的总结拖到现在,算是罪过。所以今天我就把第8-13课的内容进行梳理,对后半部分的知识进行梳理。这里推荐一个learnyounode中文版,翻译了learnyounode的界面并附上答案,对完成教程很有帮助。(当然不是抄袭。。。)中文版地址:https://www.kancloud.cn/kancloud/learnyounode/47115lesson8编写程序发起HTTPGET请求,请求的URL为提供的命令行参数第一的。收集服务器返回的所有数据(不仅仅是“数据”事件)并分两行将其打印到终端(标准输出)。对于打印的内容,第一行应该是一个整数,用来表示接收到的字符串内容的长度,第二行是服务器返回的完整字符串结果。首先要确定的是,我们从问题6和7知道,在使用node发送请求时,数据是以分片流的形式传输的,这就需要我们在收到请求后解析完整的请求。我们可以使用node的http模块请求一个接口,然后对接口返回的对应参数res进行事件处理。根据文档可以知道res有error、data、end等事件,所以这里只需要对res做事件处理就可以达到获取所有请求信息的效果。下面是代码~consthttp=require('http');http.get(process.argv[2],function(res){letrawData='';res.on('data',function(data){rawData+=data;})res.on('error',function(err){console.log(err);})res.on('end',function(data){console.log(rawData.length);console.log(rawData);})})lesson9这次的问题和之前的问题(HTTP收集器)非常相似,同样需要用到http.get()方法。但是,这一次将提供三个URL作为前三个命令行参数。需要收集每个URL返回的完整内容,然后打印到终端(stdout)上。这次不需要打印内容的长度,只需要打印内容本身(字符串形式);每个URL对应的内容为一行。重点是必须按照参数列表中这些URL的顺序排列打印相应的内容才能完成。这个问题与上一个问题类似。获取接口返回的完整信息应该是相当容易的。难点在于如何依次打印出三个接口返回的信息。当然现在npm上有这么多第三方库,我们可以通过第三方库把接口请求事件按顺序排列,完成一个接口输出返回信息,再进行下一个请求。但是我之前用笨办法在页面中处理异步。每个界面事件对应一个状态。请求接口成功返回数据后,对应的状态置为true。请求完成后,所有接口状态都为真,然后依次输出所有接口的返回信息。http=require('http');让isEnd1=false;让isEnd2=false;让isEnd3=false;让data1,data2,data3;http.get(process.argv[2],function(res){让rawData='';res.on('data',function(data){rawData+=data;})res.on('error',function(err){console.log(err);})res.on('结束',函数(数据){data1=rawData;isEnd1=true;if(isEnd1&&isEnd2&&isEnd3){console.log(data1);console.log(data2);console.log(data3);}})})http.get(process.argv[3],function(res){letrawData='';res.on('data',function(data){rawData+=data;})res.on('error',function(err){console.log(err);})res.on('end',function(data){data2=rawData;isEnd2=true;if(isEnd1&&isEnd2&&isEnd3){console.log(data1);console.log(data2);console.log(data3);}})})http.get(process.argv[4],函数(res){让rawData='';res.on('data',function(data){rawData+=data;})res.on('error',function(err){console.log(err);})res.on('end',function(data){data3=rawData;isEnd3=true;if(isEnd1&&isEnd2&&isEnd3){console.log(data1);console.log(data2);console.log(data3);}})})lesson10写一个TCP时间服务器。服务器侦听端口以获取一些TCP连接。该端口将通过第一个命令行参数传递给程序。对于每个TCP连接,您必须按照以下格式输入当前日期和24小时时间:“YYYY-MM-DDhh:mm”,后跟换行符。月、日、时、分必须补零,成为固定的两位数:“2013-07-0617:42”提示中,本题需要使用net模块创建服务器,不是http模块。作为后端新手,不懂tcp服务器和普通服务器orz的区别。希望知道的高手指点一下。知道用什么搭建服务器后,就不用担心后续的问题了,记得处理好时间格式即可。以下是手动格式化时间的代码。好像有些答案不需要手动格式化。找时间研究它的文字。constnet=require('net');net.createServer(function(socket){vardate=newDate();socket.end(formatDate(date)+'\n');}).listen(process.argv[2]);functionformatDate(datee){varyear=datee.getFullYear();varmonth=datee.getMonth()+1;vardate=datee.getDate();varhour=datee.getHours();varminute=datee.getMinutes();varsecond=datee.getSeconds();月=月<10?'0'+月:月;日期=日期<10?'0'+日期:日期;小时=小时<10?'0'+小时:小时;分钟=分钟<10?'0'+分钟:分钟;秒=秒<10?'0'+秒:秒;returnyear+'-'+month+'-'+date+''+hour+':'+minute;}lesson11编写一个HTTP文件服务器,用于将每个请求的文件返回给客户端。服务器需要侦听由提供的第一个命令行参数指定的端口。同时,将提供给程序的第二个参数是需要响应的文本文件的位置。本题必须使用fs.createReadStream()方法以流的形式响应请求。我们可以使用http和fs这两个模块在服务器发送请求时读取文件的内容,并将其内容作为流输入到接口的返回中。只需利用好fs模块的createStream方法即可完成任务。生成文件流后,我们可以通过pipe方法将其输入到接口的res中。pipe方法是stream特有的方法。我们可以把它理解为一个流变量,像管道一样流动和输出。这是一个非常抽象的方法,用在很多地方。我们可以了解更多。consthttp=require('http');constfs=require('fs');constserver=http.createServer((req,res)=>{consturl=process.argv[3];constfsdata=fs.createReadStream(url,{flags:'r',encoding:'utf-8',fd:null,mode:0o666,autoClose:true});fsdata.on('readable',()=>{console.log('readable:',fsdata.read());}).pipe(res);});server.on('clientError',(err,socket)=>{socket.end('HTTP/1.1400BadRequest\r\n\r\n');})server.on('error',(err)=>{console.log(err);})server.listen(Number(process.argv[2]),'127.0.0.1',()=>{console.log('监听成功');});第12课编写一个只接受POST请求的HTTP服务器,发送POST请求体(body)字符转换为大写返回给客户端。服务器需要监听第一个命令行参数指定的端口。在前端页面中,最常见的方式就是get和post与接口进行交互,具体的方式由接口指定。这说明后端在做界面的时候可以对前端提交的所有信息进行过滤、判断和利用,这也是通用界面所做的。所有提交给接口的信息都保存在服务端的req参数中,所以我们需要围绕这个参数判断提取信息,并返回。consthttp=require('http');http.createServer(function(req,res){varpostData='';req.addListener("data",function(postDataChunk){if(req.method==='POST'){postData+=postDataChunk;}});req.addListener("end",function(){if(req.method==='POST'){res.end(postData.toUpperCase(),'utf8');}});}).listen(process.argv[2]);第13课编写一个HTTP服务器,每当它收到一个带有路径'/api/parsetime'的GET请求时,它就会用一些JSON数据进行响应。我们希望请求中包含一个查询参数(querystring),key是“iso”,value是ISO格式的时间。例如:/api/parsetime?iso=2013-08-10T12:10:15.474Z响应JSON应仅包含三个属性:“小??时”、“分钟”和“秒”。例如:{"hour":14,"minute":23,"second":15}然后再添加一个接口,路径为'/api/unixtime',同样可以接收查询参数(querystrng),但是它的返回将包含一个属性:'unixtime',对应的值是一个UNIX时间戳。例如:{"unixtime":1376136615474}服务器需要监听命令行参数指定的第一个A端口。最后一题的意思很简单明了。结合前几题的知识,编写前端页面的界面。接口功能虽然很简单,但是涉及到前端信息判断、获取、处理、返回等一系列系统接口处理。这道题的难点在于我们需要判断信息提交的接口路径来做不同的处理。这种类似于路由的东西我们在前面的问题中都没有提到。但是上面说到服务端的req信息中包含了所有提交的信息,包括提交的接口路径、提交方式、提交内容等,所以我们按照提示使用url模块提取url中的信息req然后进行判断,达到目的。(题目中提到的isotime很难找到,本文提供一个isotime用于测试:2016-01-18T23:41:00)consthttp=require('http');consturl=require('url');constserver=http.createServer((req,res)=>{leturlObj=url.parse(req.url);letpathname=urlObj.pathname;if(pathname==='/api/parsetime'){letparam=urlObj.query;if(param.indexOf('&')===-1){letparams=param.split('=');if(params[0]==='iso'){letisotime=params[1];lettime=newDate(isotime);console.log(time);letresObj={hour:time.getHours(),minute:time.getMinutes(),second:time.getSeconds()};res.end(JSON.stringify(resObj));}}}elseif(pathname==='/api/unixtime'){letparam=urlObj.query;if(param.indexOf('&')===-1){让参数=参数.spl它('=');if(params[0]==='iso'){让isotime=params[1];让时间=新日期(isotime);让timeTamp=time.getTime();让resObj={unixtime:timeTamp};res.end(JSON.stringify(resObj));}}}})server.on('clientError',(err,socket)=>{socket.end('HTTP/1.1400BadRequest\r\n\r\n');})server.on('错误',(err)=>{console.log(err);})server.listen(Number(process.argv[2]),()=>{console.log('监听成功');})learnyounode总结到这里就结束了。感觉离node的距离又近了一步。不再像以前一样连官方的node文档都看不懂了。大致了解了各个模块的功能和调用方式后,终于把node和express区分开来了哈哈哈。感觉learnyounode虽然没有囊括node的方方面面,但是确实适合刚入门,对node一头雾水的人。单独或一起列出了node的重要模块,并列出了它们的适用场景和使用方法。但在更大程度上,我更喜欢它的提示。提示是我们以后解决节点问题的思路(提示几乎是每题必看的~还是太好了~)。在解决问题的过程中,我学到了很多东西。至少对后端的工作和权限有了一定的了解,对node的各个模块也有了一定的了解。很多知识只是自己的猜测,有失偏颇,只能等待观念的不断深入和逐步修正。在实践过程中,fs和http模块的强大给我留下了深刻的印象,对网络爬虫的工作原理也有了大概的了解。过一段时间,我应该写爬虫来巩固和加深这些知识。在这里立个flag也算是给自己定了个小目标吧~
