-
Notifications
You must be signed in to change notification settings - Fork 52
异步流程管理
LYF edited this page Apr 27, 2017
·
24 revisions
有一个url,存储在一个名为url.file
的文件内,内有一行json:
http://xxx.yyy.com/test.json
这个json的内容为:
{
"name": "李彦峰",
"age": 26
}
我想要先读取这个文件,然后下载这个url,并parse成一个对象,然后给age属性进行加1操作,然后在写回本地的json.file
文件里。
整个流程为:读 -> 下载 -> 解析 -> age加1 -> 写回
/**
点评:这种方式很啰嗦,代码量多,回调嵌套回调,可读性也不好。
这就是所谓的“回调地域”,好在我们parse的时候,是同步的。
不然还要在parse的回调中调用write
**/
const read = (file, cb) => {
fs.readFile(file, 'utf8', (err, url) => {
if(err){
console.error(err)
} else {
console.log('45:', url)
cb(url)
}
})
}
const download = (url, cb) => {
request(url, (err, response, json) => {
if (!err && response.statusCode === 200) {
cb(json)
} else {
console.error(err)
}
})
}
const parse = (res) => {
const obj = JSON.parse(res)
obj.age++
return JSON.stringify(obj)
}
const write = (text, file = './json.file') => {
fs.writeFile(file, text, 'utf8', (err) => {
console.error(err)
})
}
read('./url.file', (url) => {
download(url, (res) => {
const str = parse(res)
write(str)
})
})
Promise我们使用bluebird
,为了减少代码我没有使用 return new Promise
的方式,而是使用了 Promise.promisify
的方式,来promise化readFile/request/writeFile
这三个异步方法
/**
点评:这种方式相对于刀耕火种的回调函数方式就好了很多.
代码很易读,就跟写文章一样,then这个单词就是*然后*的意思,
我们可以看到代码的意思是:先读取`url.file`这个文件,然后下载,然后解析,然后写入。
流程非常清晰,非常有语义化。
最关键的是,异常处理也变得很方便。
**/
const read = (file) => Promise.promisify(fs.readFile)(file, 'utf8')
const download = (url) => Promise.promisify(request)(url)
const parse = (res) => {
const obj = JSON.parse(res.body)
obj.age++
return JSON.stringify(obj)
}
const write = (text, file = './json.file') => Promise.promisify(fs.writeFile)(file, text, 'utf8')
read('./url.file')
.then(download)
.then(parse)
.then(write)
.catch(e => console.error(e))
/**
点评:这种方式个人感觉相对于Promise的方式又好了一些.
把Promise的水平结构,拉成了垂直结构,跟传统的同步语言,比如Java、C等很像
**/
const read = (file) => Promise.promisify(fs.readFile)(file, 'utf8')
const download = (url) => Promise.promisify(request)(url)
const parse = (res) => {
const obj = JSON.parse(res.body)
obj.age++
return JSON.stringify(obj)
}
const write = (text, file = './json.file') => Promise.promisify(fs.writeFile)(file, text, 'utf8')
const flow = async (file) => {
const url = await read(file)
const res = await download(url)
const str = parse(res)
write(str)
}
flow('./url.file')
- async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
- async/await是基于Promise实现的,它不能用于普通的回调函数。
- async/await与Promise一样,是非阻塞的。
- async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
- async函数会隐式地返回一个promise,该promise的reosolve值就是函数return的值。(示例中reosolve值就是字符串"done")