鸣人火影之路的第一步,就是跟着卡卡西学习基本的忍术,让自己先在忍者的世界里生存下来,so,想要在 node 的世界里游刃有余,必须要掌握异步 I/O、http等核心技能。

ok,第一步先学会读懂需求

// NO1:
// Create a program that prints a list of files in a given directory,filtered by the extension of the files. You will be provided a directory name as the first argument to your program (e.g. '/path/to/dir/') and a file extension to filter by as the second argument. For example, if you get 'txt' as the second argument then you will need to filter the list to only files that end with .txt. Note that the second argument will not come prefixed with a '.'. The list of files should be printed to the console, one file per line. You must use asynchronous I/O. // tips
// The fs.readdir() method takes a pathname as its first argument and a callback as its second. The callback signature is: function callback (err, list) { /* ... */ } // where list is an array of filename strings. //You may also find node's path module helpful, particularly the extname method.
// The answer at the bottom
 
// NO2:
// This problem is the same as the previous but introduces the concept of modules. You will need to create two files to solve this.
// Create a program that prints a list of files in a given directory, filtered by the extension of the files. The first argument is the directory name and the second argument is the extension filter. Print the list of files (one file per line) to the console. You must use asynchronous I/O.
// You must write a module file to do most of the work. The module must export a single function that takes three arguments: the directory name, the filename extension string and a callback function, in that order. The filename extension argument must be the same as what was passed to your program. Don't turn it into a RegExp or prefix with "." or do anything except pass it to your module where you can do what you need to make your filter work.
// The callback function must be called using the idiomatic node(err, data) convention. This convention stipulates that unless there's an error, the first argument passed to the callback will be null, and the second will be your data. In this exercise, the data will be your filtered list of files, as an Array. If you receive an error, e.g. from your call to fs.readdir(), the callback must be called with the error, and only the error, as the first argument.
// You must not print directly to the console from your module file, only from your original program. // These four things are the contract that your module must follow.
// 1. Export a single function that takes exactly the arguments described.
// 2. Call the callback exactly once with an error or some data as described.
// 3. Don't change anything else, like global variables or stdout.
// 4. Handle all the errors that may occur and pass them to the callback. // The benefit of having a contract is that your module can be used by anyone who expects this contract. So your module could be used by anyone else who does learnyounode, or the verifier, and just work. // tips
// The answer at the bottom
// Create a new module by creating a new file that just contains your directory reading and filtering function. To define a single function export, you assign your function to the module.exports object, overwriting what is already there: module.exports = function (args) { /* ... */ } // Or you can use a named function and assign the name. // To use your new module in your original program file, use the require() call in the same way that you require('fs') to load the fs module. The only difference is that for local modules must be prefixed with './'. So,
// if your file is named mymodule.js then: var mymodule = require('./mymodule.js')

怎么样?是不是发现自己有时连需求都看不懂!没关系,下面就是中文了,不过最新的、高质量的新技术都是通过英语来传播的,所以最好还是坚持学英语,读英语技术书籍、博客!

// NO3
// 这次的问题需要使用到 http.get() 方法。然而,这一次,将有三个 URL 作为前三个命令行参数提供给你。
// 你需要收集每一个 URL 所返回的完整内容,然后将它们在终端(标准输出stdout)打印出来。这次你不需要打印出这些内容的长度,仅仅是内容本身即可(字符串形式);每个 URL 对应的内容为一行。重点是你必须按照这些URL在参数列表中的顺序将相应的内容排列打印出来才算完成。 // 提示
// 不要期待这三台服务器能好好的一起玩耍!他们可能不会把完整的响应的结果按照你希望的顺序返回给你,所以你不能天真地只是在收到响应后直接打印出来,因为这样做的话,他们的顺序可能会乱掉。
// 你需要去跟踪到底有多少 URL 完整地返回了他们的内容,然后用一个队列存储起来。一旦你拥有了所有的结果,你才可以把它们打印到终端。
// NO4:编写一个 TCP 时间服务器  

// 你的服务器应当监听一个端口,以获取一些 TCP 连接,这个端口会经由第一个命令行参数传递给你的程序。针对每一个 TCP 连接,你都必须写入当前的日期和24小时制的时间,如下格式:  

//     "YYYY-MM-DD hh:mm"  

//  然后紧接着是一个换行符。  

//  月份、日、小时和分钟必须用零填充成为固定的两位数:  

//     "2013-07-06 17:42"  

// 提示
// 这次练习中,我们将会创建一个 TCP 服务器。这里将不会涉及到任何 HTTP 的事情,因此我们只需使用 net 这个 Node 核心模块就可以了。它包含了所有的基础网络功能。 // net 模块拥有一个名叫 net.createServer() 的方法,它会接收一个回调函数。和 Node 中其他的回调函数不同,createServer() 所用的回调函数将会被调用多次。你的服务器每收到一个 TCP 连接,都会调用一次这个回调函数。这个回调函数有如下特征: function callback (socket) { /* ... */ } // net.createServer() 也会返回一个 TCP 服务器的实例,你必须调用 server.listen(portNumber) 来让你的服务器开始监听一个特定的端口。 // 一个典型的 Node TCP 服务器将会如下所示: var net = require('net')
var server = net.createServer(function (socket) {
// socket 处理逻辑
})
server.listen(8000) //socket 对象包含了很多关于各个连接的信息(meta-data),但是它也同时是一个 Node 双工流(duplex Stream),所以,它即可以读,也可以写。对这个练习来说,我们只需要对 socket 写数据和关闭它就可以了。 // 使用 socket.write(data) 可以写数据到 socket 中,用 socket.end() 可以关闭一个 socket。另外, .end() 方法也可以接收一个数据对象作为参数,因此,你可简单地使用 socket.end(data) 来完成写数据和关闭两个操作。
// NO5
// 编写一个 HTTP 文件 服务器,它用于将每次所请求的文件返回给客户端。 你的服务器需要监听所提供给你的第一个命令行参数所制定的端口。 同时,第二个会提供给你的程序的参数则是所需要响应的文本文件的位置。在这一题中,你必须使用 fs.createReadStream() 方法以 stream 的形式作出请求相应。
// 提示
//一个典型的 Node HTTP 服务器将会是这个样子: var http = require('http')
var server = http.createServer(function (req, res) {
// 处理请求的逻辑...
})
server.listen(8000) // fs 这个核心模块也含有一些用来处理文件的流式(stream) API。你可以使用 fs.createReadStream() 方法来为命令行参数指定的文件创建一个 stream。这个方法会返回一个 stream 对象,该对象可以使用类似 src.pipe(dst) 的语法把数据从 src流传输(pipe) 到 dst流中。通过这种形式,你可以轻松地把一个文件系统的 stream 和一个 HTTP 响应的 stream 连接起来。
// NO6
// 编写一个 HTTP 服务器,它只接受 POST 形式的请求,并且将 POST 请求主体(body)所带的字符转换成大写形式,然后返回给客户端。 // 提示
// through2-map 允许你创建一个 transform stream,它仅需要一个函数就能完成「接收一个数据块,处理完后返回这个数据块」 的功能 ,它的工作模式类似于 Array#map(),但是是针对 stream 的: var map = require('through2-map')
inStream.pipe(map(function (chunk) {
return chunk.toString().split('').reverse().join('')
})).pipe(outStream)
// NO7 HTTP JSON API 服务器 

// 编写一个 HTTP 服务器,每当接收到一个路径为 '/api/parsetime' 的 GET 请求的时候,响应一些 JSON 数据。我们期望请求会包含一个查询参数(query string),key 是 "iso",值是 ISO 格式的时间。  

  /api/parsetime?iso=2013-08-10T12:10:15.474Z  

//  所响应的 JSON 应该只包含三个属性:'hour','minute' 和 'second'。例如:  

     {
"hour": 14,
"minute": 23,
"second": 15
} // 然后增再加一个接口,路径为 '/api/unixtime',它可以接收相同的查询参数(query string),但是它的返回会包含一个属性:'unixtime',相应值是一个 UNIX 时间戳。例如: { "unixtime": 1376136615474 } //提示
// 你可以使用 Node 的核心模块 'url' 来处理 URL 和 查询参数(query string)。 url.parse(request.url, true) 方法会处理 request.url,它返回的对象中包含了一些很有帮助的属性,方便方便你处理 querystring。
// 你也应当争做 Web 世界的好公民,正确地为响应设置 Content-Type 属性: res.writeHead(200, { 'Content-Type': 'application/json' })

Pseudo code

// NO1
   var fs = require('fs')
var path = require('path') var folder = process.argv[2]
var ext = '.' + process.argv[3] fs.readdir(folder, function (err, files) {
if (err) return console.error(err)
files.forEach(function (file) {
if (path.extname(file) === ext) {
console.log(file)
}
})
})
// NO2
// ./solution/solution.js_ : var filterFn = require('./solution_filter.js')
var dir = process.argv[2]
var filterStr = process.argv[3] filterFn(dir, filterStr, function (err, list) {
if (err) {
return console.error('There was an error:', err)
} list.forEach(function (file) {
console.log(file)
})
}) // ./solution/solution_filter.js_ : var fs = require('fs')
var path = require('path') module.exports = function (dir, filterStr, callback) {
fs.readdir(dir, function (err, list) {
if (err) {
return callback(err)
} list = list.filter(function (file) {
return path.extname(file) === '.' + filterStr
}) callback(null, list)
})
}
// NO3
var http = require('http');
var i = 2,
aCon = []; function filterFn(aUrl) { if (i < 5) {
http.get(aUrl[i], function (res) {
res.setEncoding('utf8');
let rowData = ''; res.on('data', function (data) {
rowData += data;
}).on('end', ()=>{
i++;
aCon.push(rowData);
filterFn(aUrl);
}).on('error', (e) => {
console.log($(e.message));
});
});
} else {
aCon.forEach(function (val) {
console.log(val);
});
}
} filterFn(process.argv);
// NO4
var net = require('net') function zeroFill (i) {
return (i < 10 ? '0' : '') + i
} function now () {
var d = new Date()
return d.getFullYear() + '-' +
zeroFill(d.getMonth() + 1) + '-' +
zeroFill(d.getDate()) + ' ' +
zeroFill(d.getHours()) + ':' +
zeroFill(d.getMinutes())
} var server = net.createServer(function (socket) {
socket.end(now() + '\n')
}) server.listen(Number(process.argv[2]))
    // NO5
var http = require('http')
var fs = require('fs') var server = http.createServer(function (req, res) {
res.writeHead(200, { 'content-type': 'text/plain' }) fs.createReadStream(process.argv[3]).pipe(res)
}) server.listen(Number(process.argv[2]))
// NO6
const server = http.createServer((req, res) => {
if (req.method != 'POST') {
return res.end('send a POST\n');
} req.pipe(map(function (chunk) {
return chunk.toString().toUpperCase();
})).pipe(res);
}); server.listen(Number(process.argv[2]));
    // NO7
var http = require('http')
var url = require('url') function parsetime (time) {
return {
hour: time.getHours(),
minute: time.getMinutes(),
second: time.getSeconds()
}
} function unixtime (time) {
return { unixtime: time.getTime() }
} var server = http.createServer(function (req, res) {
var parsedUrl = url.parse(req.url, true)
var time = new Date(parsedUrl.query.iso)
var result if (/^\/api\/parsetime/.test(req.url)) {
result = parsetime(time)
} else if (/^\/api\/unixtime/.test(req.url)) {
result = unixtime(time)
} if (result) {
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify(result))
} else {
res.writeHead(404)
res.end()
}
})
server.listen(Number(process.argv[2]))

PS: nodeSchool

Ninja 之路:试炼!求生演习——异步 I/O、http的更多相关文章

  1. 嵌入式Linux驱动学习之路(十三)按键驱动-异步通知

    之前的按键方式: 查询: 极度占用CPU资源 中断: 在读的时候产生休眠,在没有信号的时候永远不会返回. poll机制: 在中断的基础上加上超时时间. 异步通知就是通过信号来传送. 首先在应用程序中有 ...

  2. IOS学习之路七(使用 Operation 异步运行任务)

    在 application delegate 头文件(.h)中声明一个 operation 队列和两个 invocation operations: #import <UIKit/UIKit.h ...

  3. 【CLR VIA C#】读书笔记

    工作几年了才看,记录下笔记备忘. 章节 笔记 1.CLR的执行模型 公共语言运行时(Common Language Runtime,CLR) 源代码-->编译器检查语法和分析源代码-->托 ...

  4. vue ssr 项目改造经历

    vue ssr 项目改造经历 由于工作项目需求,需要将原有的项目改造,vue ssr 没有用到nuxt,因为vue ssr更利于seo,没办法,一个小白的改造经历, 首先说明一下,小白可以借鉴,高手也 ...

  5. Linux日志管理系统rsyslog

    一.日志的概念 什么是日志?日志就是历史事件.历史事件包括时间.地点.人物.时间.这个是生活中所说的日志很好理解.在Linux中也有类似的服务,它主要作用就是记录Linux系统的历史事件,包括什么时间 ...

  6. Python之路,Day10 - 异步IO\数据库\队列\缓存

    Python之路,Day9 - 异步IO\数据库\队列\缓存   本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...

  7. Node.js之路【第三篇】NodeJS异步实现

    NodeJS异步实现 Node.js异步编程的直接体现就是回调,它依托于回调来实现,但不能说使用了回调他就是异步了 回调函数在完成任务后就会被调用,Node使用了大量的回调函数,Node所有的API都 ...

  8. Python之路第一课Day10--随堂笔记(异步IO\数据库\队列\缓存)

    本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SS ...

  9. EF架构~EF异步改造之路~仓储接口的改造

    回到目录 返回异步与并行目录 C#5.0带来了并行编程 {C#1.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语言→C#5.0异步编程} 随着C#5.0在.net4.5出来之后,它们 ...

随机推荐

  1. JS 拖动DIV 需要JQUERY 支持

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. VisualVM监控远程主机上的JAVA应用程序

    使用VisualVM监控远程主机上JAVA应用程序时,需要开启远程主机上的远程监控访问,或者在远程JAVA应用程序启动时,开启远程监控选项,两种方法,选择其中一种就可以开启远程监控功能,配置完成后就可 ...

  3. python多版本的pip共存问题解决办法

    python pip 多版本 问题情景 最开始学python的时候用的是py2,且一直用pip来安装库函数.后来py3出来了,所以就装上了,但是一装上出问题了,主要有两个主要的问题.下面将详细说明. ...

  4. selenium自动化--(JAVA方法写的)第一章 源代码工程的导入

    1.首先打开eclipse,找到eclipse的工程窗口界面,依次找到"import-->import"功能 2.在弹出来的导入对话框中,选择导入已存在的工程"Ex ...

  5. 初步认识Thymeleaf:简单表达式和标签。(一)

    本文只适用于不会Java对HTML语言有基础的程序员们,是浏览了各大博客后收集整理,重新编辑的一篇文章,希望能对大家有所帮助. 对于Thymeleaf,网上特别官方的解释无非就是:网站或者独立应用程序 ...

  6. jenkins+SVN配置

    开发项目,版本控制必不可少,我用的版本控制软件为SVN,那么如何把jenkins和SVN结合,使得SVN源码一有上传更新,jenkins就马上构建项目呢?下面说一下配置过程   1)         ...

  7. [原]C#与非托管——初体验

    P/Invokes初看起来非常简单,利用DllImport进行extern函数的声明,程序就可以在调用extern函数的时候自动查询调用到对应的非托管函数,有些类似Java的native函数,但更为简 ...

  8. TCP/IP笔记(四)IP协议

    前言 IP相当于OSI参考模型的第3层--网络层:主要作用是"实现终端节点之间的通信"又称"点对点通信". IP作为整个TCP/IP中至关重要的协议,主要负责将 ...

  9. 云计算+SaaS+业务开发平台=JSAAS云平台

    我关注Google的代码托管.Open API,我也关注Oracle会把MYSQL怎么样云数据库化,我也虚拟化技术多实例化独立的数据库,我也关注facebook的平台插件应用架构,我也关注salesf ...

  10. 老李分享:大数据测试中java和hadoop关系

    Hadoop的创始人是Doug Cutting, 同时也是著名的基于Java的检索引擎库Apache Lucene的创始人.Hadoop本来是用于著名的开源搜索引擎Apache Nutch,而Nutc ...