基础语法
手写promise
常见面试题
在nodejs中充斥着大量的回调代码,很不利于项目的维护,且在开发阶段也带来了不必要的逻辑复杂度
本文将结合动态设置响应头的例子通过对readline函数改造,帮助大家更好的学习promise
首先,原生nodejs的实现可能是这样的
constreadline =require('readline')
const rl = readline.createInterface({input: process.stdin})
rl.on('line', (input) => {console.log(`接收到:${input}`);})
改造后
1-我们考虑将异步代码封装为promise
new Promise(resolve=>{
rl.on('line', (input) => {console.log(`接收到:${input}`);})
})
2-对于promise的值如果我们想读取就必须通过then方法,这在模块化开发时,经常需要对我们已经写好的功能copy到then中,这很可能会造成之前的逻辑跑不起来,因此我们考虑加入async+await
async function getLine(){
return new Promise(resolve=>{
rl.on('line', (input) => {console.log(`接收到:${input}`);})
})
}
3-这样我们便可以在调用处这样使用
let res = await getLine()
知道了为什么以及如何使用promise后,就让我们来实现这样一个需求吧
需求:根据请求的文件类型动态设置响应头
1-首先我们需要准备这样一个.txt文件,它包含了所有的响应类型(类型请自行百度哦)
每一行的格式如下:.html|text/html
2-搭建一个web服务
const http = require('http')
http.createServer((req,res)=>{
res.writeHead(200,"Content-Type:text/html;charset='utf-8'")
res.end()
}).listen(3000)
3-我们设置的响应头是固定的,不管是css还是js又或者png请求,我们都返回text/html,虽然这在chrome中并没有出现异常,但是你不能保证用户总是使用最新的chrome,你也无法要求用户只使用chrome,因此我们新建一个模块getLine
const readline = require('readline')
const rl = readline.createInterface({input: process.stdin})
async function getLine(){
return new Promise(resolve=>{
rl.on('line', (line) => {
if(当前读取的这一行正好是我们请求的文件类型){
//不在向下读取
rl.close()
resolve(line)
}
})
})
}
module.exports = getLine
4-在app中引入我们新建的用于读取文件类型的模块,并动态替换响应头
const getLine = require('getLine')
const url = require('url')
const path = require('path')
let isExt = path.extname(url.parse(req.url,true).pathName)
if(后缀名isExt存在){
let mine = await getLine(isExt)
res.writeHead(200,`Content-Type:${mine};charset='utf-8'`)
}
至此,大功告成