全屏

nodejs, promise, generator

赵旭东

所有可执行代码位于 https://github.com/zxdong262/promise-generator-demo

请确保node版本 >= 0.11.13

git clone https://github.com/zxdong262/promise-generator-demo.git
cd promise-generator-demo
npm install
node test1.js
#node test-with-file-read.js
#node test-with-3file-read.js
#node test-with-file-read-promise.js
#node test-with-3file-read-sync.js
#node test-with-3file-read-generator.js


nodejs原理

  1. 主进程只执行非阻塞操作
  2. 把耗时的操作交给后台,在执行完毕后,才回到主进程执行
  3. 通过callback机制实现

nodejs原理

官网的例子

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test1.js

var http = require('http');

http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

加入一个读取文件操作

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test-with-file-read.js

var http = require('http')
,fs = require('fs')


http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'})

  //read file
  fs.readFile('a.txt',  function(err, txt) {
    response.end(txt)
  })
  
}).listen(8124)

console.log('Server running at http://127.0.0.1:8124/')

Callback Hell!

如果要读三个文件...

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test-with-3file-read.js

var http = require('http')
,fs = require('fs')

http.createServer(function (request, response) {
  var txt = ''
  response.writeHead(200, {'Content-Type': 'text/plain'})

  //read file
  fs.readFile('a.txt',  function(err, txt1) {
    txt = txt + txt1
    fs.readFile('b.txt',  function(err, txt2) {
      txt = txt + txt2
      fs.readFile('c.txt',  function(err, txt3) {
        txt = txt + txt3
        response.end(txt)
      })
    })
  })
  
}).listen(8124)

console.log('Server running at http://127.0.0.1:8124/')

Promise!

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test-with-file-read-promise.js

var http = require('http')
,fs = require('fs')
,readFile = function(file) {
  return new Promise(function(resolve, reject) {
    fs.readFile(file,  function(err, fileContent) {
      if(err) reject(err)
      else resolve(fileContent)
    })
  })
}

Promise!

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test-with-file-read-promise.js

http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'})

  //read file
  var txt = ''
  readFile('a.txt')
  .then(function(tx) {
    txt = txt + tx
    return readFile('b.txt')
  })
  .then(function(tx) {
    txt = txt + tx
    return readFile('c.txt')
  })
  .then(function(tx) {
    txt = txt + tx
    response.end(txt)
  })
  .catch(function(err) {
    console.log(err.stack)
  })

  
}).listen(8124)

Promise!

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test-with-3file-read-sync.js

/* 同步 */
Promise.all([readFile('a.txt'), readFile('b.txt'), readFile('c.txt')])
.then(function(arr) {
  response.end(arr.join(''))
})
.catch(function(err) {
  console.log(err.stack)
})

with generator

代码https://github.com/zxdong262/promise-generator-demo/blob/master/test-with-file-read-generator.js

var co = require('co')

http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'})

  //read file
  var cof = co.wrap(function* () {
    var a = yield readFile('a.txt')
    var b = yield readFile('b.txt')
    var c = yield readFile('c.txt')
    return a + b + c
  })
  
  cof()
  .then(function(txt) {
    response.end(txt)
  })
  
}).listen(8124)

in koa

route.get('/', function* (next) {

  //read file one by one
  var a = yield readFile('a.txt')
  var b = yield readFile('b.txt')
  var c = yield readFile('c.txt')
  this.body =  a + b + c
  
})

in koa

route.get('/', function* (next) {

  //read file in parall
  var files = yield [
    readFile('a.txt')
    ,readFile('b.txt')
    ,readFile('c.txt')
  ]

  this.body =  files.join('')
  
})

未来: ES7 await, async

async function act() {
  var a = await readFile('a.txt')
  var b = await readFile('b.txt')
  var c = await readFile('c.txt')
  response.end( a + b + c )
})
act()

全屏