Async

2018-08-23  本文已影响0人  _小山楂

1. 异步

asyncfunc1.png

这种不连续的执行,就叫做异步。相应地,连续的执行,就叫做同步。

syncfunc.png

2.高阶函数

函数作为一等公民,可以作为参数和返回值

2.1 可以用于批量生成函数

let toString = Object.prototype.toString;
let isString = function (obj) {
  return toString.call(obj) == `[object String]`;
}
let isFunction = function (obj) {
  return toString.call(obj) == `[object Function]`;
}
let isType = function (type) {
  return function (obj) {
    return toString.call(obj) == `[object ${type}]`;
  }
}

2.2 可以用于需要调用多次才执行的函数

let after = function(times,task){
  return function(){
    if(times--==1){
      return task.apply(this,arguments);
    }
  }
}
let fn = after(3,function(){
  console.log(3);});
fn();

3. 异步编程的语法目标,就是怎样让它更像同步编程,有以下几种

4.回调

所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数


fs.readFile('某个文件', function (err, data) {

  if (err) throw err;

  console.log(data);

});

​ 这是一个错误优先的回调函数(error-first callbacks),这也是Node.js本身的特点之一。

5 回调的问题

5.1 异常处理


try{

  //xxx

}catch(e){//TODO}

​ 异步代码时try catch不再生效


let async = function(callback){

  try{

    setTimeout(function(){

      callback();

    },1000)

  }catch(e){

    console.log('捕获错误',e);

  }

}

async(function(){

  console.log(t);

});

​ 因为这个回调函数被存放了起来,直到下一个事件环的时候才会取出,try只能捕获当前循环内的异常,对callback异步无能为力。

Node在处理异常有一个约定,将异常作为回调的第一个实参传回,如果为空表示没有出错。


async(function(err,callback){

  if(err){

    console.log(err);

  }

});

异步方法也要遵循两个原则

5.2 回调地狱

异步多级依赖的情况下嵌套非常深,代码难以阅读的维护

let fs = require('fs');

fs.readFile('template.txt','utf8',function(err,template){

fs.readFile('data.txt','utf8',function(err,data){

  console.log(template+' '+data);

})

})

6. 异步流程解决方案

6.1 事件发布/订阅模型

订阅事件实现了一个事件与多个回调函数的关联

let fs = require('fs');

let EventEmitter = require('events');

let eve = new EventEmitter();

let html = {};

eve.on('ready',function(key,value){

  html[key] = value;

  if(Object.keys(html).length==2){

    console.log(html);

  }

});

function render(){

  fs.readFile('template.txt','utf8',function(err,template){

    eve.emit('ready','template',template);

  })

  fs.readFile('data.txt','utf8',function(err,data){

    eve.emit('ready','data',data);

  })

}

render();

6.2 哨兵变量

let fs = require('fs');

let after = function(times,callback){

  let result = {};

  return function(key,value){

    result[key] = value;

    if(Object.keys(result).length==times){

      callback(result);

    }

  }

}

let done = after(2,function(result){

  console.log(result);

});

function render(){

  fs.readFile('template.txt','utf8',function(err,template){

    done('template',template);

  })

  fs.readFile('data.txt','utf8',function(err,data){

    done('data',data);

  })

}

6.3 Promise/Deferred模式

6.4 生成器Generators/ yield

#### 6.4.2 Co 

`co`是一个为`Node.js`和浏览器打造的基于生成器的流程控制工具,借助于Promise,你可以使用更加优雅的方式编写非阻塞代码。

```js 
let fs = require('fs');

function readFile(filename) {

  return new Promise(function (resolve, reject) {

    fs.readFile(filename, function (err, data) {

      if (err)

        reject(err);

      else

        resolve(data);

    })

  })

}

function *read() {

  let template = yield readFile('./template.txt');

  let data = yield readFile('./data.txt');

  return template + '+' + data;

}

co(read).then(function (data) {

  console.log(data);

}, function (err) {

  console.log(err);

});

```



```js
function co(gen) {

  let it = gen();

  return new Promise(function (resolve, reject) {

    !function next(lastVal) {

      let {value, done} = it.next(lastVal);

      if (done) {

        resolve(value);

      } else {

        value.then(next, reason = reject(reason));

      }

    }();

  });

}

```

## 6.5 Async/ await 

使用`async`关键字,你可以轻松地达成之前使用生成器和co函数所做到的工作

### 6.5.1 Async的优点 
### 6.5.2 async 函数的实现
async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。



```js
async function read() {
  let template = await readFile('./template.txt');
  let data = await readFile('./data.txt');
  return template + '+' + data;
}

// 等同于
function read(){
  return co(function*() {
    let template = yield readFile('./template.txt');
    let data = yield readFile('./data.txt');
    return template + '+' + data;
  });
}
```
上一篇 下一篇

猜你喜欢

热点阅读