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