Skip to content
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 -> 写回

二、 上述流程的编程实现

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)
  })
})

2. Promise方式

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))

3. async的方式

/**
 点评:这种方式个人感觉相对于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')

4. async/await

  • async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
  • async/await是基于Promise实现的,它不能用于普通的回调函数。
  • async/await与Promise一样,是非阻塞的。
  • async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
  • async函数会隐式地返回一个promise,该promise的reosolve值就是函数return的值。(示例中reosolve值就是字符串"done")

参考:http://www.cnblogs.com/fundebug/p/6667725.html

Clone this wiki locally