异步编程

AJAX中的回调函数

Ajax(Asynchronous JavaScript and XML)基于XMLHTTPRequest对象实现,在浏览器中使用AJAX

function ajax(url,callback){
  var xhr = new XMLHttpRequest(); //新建xhr对象
  xhr.onreadystatechange = function(){ //检测readystatechange事件
    if(xhr.readyState === XMLHttpRequest.DONE){ //当请求已经完成
      if(xhr.status = 200){ //如果服务器响应没有错误
        callback(null,xhr.responseText);
      }else{
        callback(xhr.status);
      }
    }
  }
  xhr.open("GET",url);//建议连接
  xhr.send(null);//发送body为空的数据
}

XMLHttpRequest在使用POST方式提交数据时,需要根据服务器端接口实现方式添加对应HTTP头。如果采用表单方式提交数据,则需要设置Content-Type,代码如下:

xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

使用先前创建的ajax函数异步请求数据:

ajax(url,function(err,data){
  if(err){
    console.log(err);
  }else{
    console.log('the response body is '+data);
  }
})

Promise模式

上述采用了callback方式实现异步编程,实际项目中层层嵌套容易造成回调地狱,如下:

ajax('http://apiA',function(dataA){
  ajax('http://apiB',function(dataB){
    ajax('http://apiC',function(dataC){
      //...
    });
  });
});

ES6提供了Promise对象,有效解决这一问题,采用Promise对象对之前定义的ajax函数进行包装:

function ajax(url){
  return new Promise(function(resolve,reject){
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
      if(xhr.readyState === XMLHttpRequest.DONE){
        if(xhr.status === 200){
          //成功时,结果采用resolve回调返回
          resolve(xhr.responseText);
        }else{
          //失败时,将出错信息采用reject回调返回
          reject(new Error('请求错误编码:'+xhr.status));
        }
      }
    };
    xhr.open("get",url);
    xhr.send(null);
  });
}

在调用异步操作时,直接使用Promise对象的实例方法执行成功和失败的操作:

ajax('/writer/dravenxiaokai').then(data=>{
  //data中包含返回的内容
}).catch(err=>{
  //err包含错误异步调用的错误信息
});

同时then方法支持多次链式调用

ajax('/author/dravenxiaokai').then(function(data){
  data.a = 'some value';
  return data;
}).then(function(data){
  //...
}).catch(function(err){
  //...
})

对于多重嵌套的异步调用,可以很方便的用过Promise实现,只需要在成功回调后,返回一个新的Promise对象即可,代码如下:

ajax('http://api1').then(function(data){
  return ajax('http://api2');//返回一个新的Promise对象
}).then(function(data){
  //data参数为api2返回的数据
})

生成器Generator

function* gen(){//定义一个生成器
  yield 1;//通过yield关键字,产出1
  yield 2;//通过yield关键字,产出2
  return 3;返回3
}
var g = gen();
g.next();//{value:1,done:false}
g.next();//{value:2,done:false}
g.next();//{value:3,done:true}
g.next();//{value:undefined,done:true}

在生成器中使用异步调用

function* demo(){
  var a = Promise.resolve(1);
  var b = Promise.resolve(a + 2);
  var c = Promise.resolve(b + 3);
  return c;
}
function co(generator){
  var gen = generator();
  function nextFunc(arg){
    var next = gen.next(arg);//首先执行以下next,取到第一个Promise
    if(!next.done){//如果生成器没有完成时,执行这个Promise
      next.value.then(function(data){
        console.log(data);
        nextFunc(data);
      });
    }else if(next.value){
      console.log(next.value);
    }
  };
  nextFunc();
}
co(demo);

关键字async & await

async function es7(){
  var a = await Promise.resolve(1);
  var b = await Promise.resolve(a * 2);
  var c = await Promise.resolve(b + 3);
  return c;
}
es7().then(function(data){//异步调用函数执行的结果是Promise对象
  console.log(data)
})

你可能感兴趣的:(异步编程)