js的异步
(1)异步调用
- 定时任务
- Ajax
- 事件函数
(2)多次异步调用的依赖分析
- 结果顺序不确定
- 如果调用结果存在顺序,则需要嵌套----导致“回调地狱”的问题
Promise
解决异步深层嵌套的问题
- Promise是一个(函数)对象
console.log(typeof Promise)
console.dir(Promise);
基本用法:
- resolve()成功
- reject()失败
- p.then 得到结果
var p=new Promise(function(resolve, reject){
//resolve()成功
//reject()失败
});
p.then(function(data){
//从resolve得到正常结果
},function(info){
//从reject得到异常结果
});
案例:
<script type="text/javascript">
//参数:resolve和reject是函数
var p = new Promise(function(resolve, reject){
// 这里用于实现异步任务
setTimeout(function(){
var flag = false;
if(flag) {
// 正常情况
resolve('hello');
}else{
// 异常情况
reject('出错了');
}
}, 100);
});
p.then(function(data){
//成功的结果信息
console.log(data)
},function(info){
//失败的结果信息
console.log(info)
});
</script>
结果:当flag为false时,控制台输出 出错了;当flag为true时,控制台输出 hello
基于Promise发送Ajax请求
(1)一次ajax请求
<script type="text/javascript">
//queryData函数返回一个Promise对象
function queryData(url) {
var p = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
// 处理正常的情况
resolve(xhr.responseText);
}else{
// 处理异常情况
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
return p;
}
queryData('http://localhost:3000/data')
.then(function(data){
//发送请求成功返回的数据
console.log(data);
},function(info){
//发送请求失败返回的数据
console.log(info)//服务器错误
});
</script>
(2)多次ajax请求
// 发送多个ajax请求并且保证顺序
queryData('http://localhost:3000/data')//请求1次
.then(function(data){//只看正常的情况
console.log(data)
return queryData('http://localhost:3000/data1');//请求2次
})
.then(function(data){
console.log(data);
return queryData('http://localhost:3000/data2');//请求3次
})
.then(function(data){
console.log(data)
});
Promise 基本API
(1)实例方法:
- p.then() 得到异步任务正确的结果
- p.catch() 获取异常信息
- p.finally() 成功与否都会执行
<script type="text/javascript">
function foo() {
return new Promise(function(resolve, reject){
setTimeout(function(){
// resolve(123);
reject('error');
}, 100);
})
}
//写法一:
foo()
.then(function(data){
console.log(data)
})
.catch(function(data){
console.log(data)
})
.finally(function(){
console.log('finished')
});
// --------------------------
// 两种写法是等效的
//写法二:
foo()
.then(function(data){
console.log(data)
},function(data){
console.log(data)
})
.finally(function(){
console.log('finished')
});
</script>
结果:resolve时,是 123 finished;reject时,是 error finished。
(2)静态方法:
- Promise.all() 并发处理多个异步任务,所有任务都执行完成才得到结果
- Promise.race() 并发处理多个异步任务,只要有一个任务执行完成就得到结果
定义:
Promise.all([p1,p2,p3]).then(result=>{
console.log(result)
});
Promise.race([p1,p2,p3]).then(result=>{
console.log(result)
});
使用:
var p1 = queryData('http://localhost:3000/a1');//发送ajax请求,得到Promise对象p1
var p2 = queryData('http://localhost:3000/a2');
var p3 = queryData('http://localhost:3000/a3');
Promise.all([p1,p2,p3]).then(function(result){
console.log(result)
})
//-------------------------------------------
Promise.race([p1,p2,p3]).then(function(result){
//由于p1执行较快,Promise的then()将获得结果'P1'。p2,p3仍在继续执行,但执行结果将被丢弃
console.log(result)
})
fetch
- 更简单的数据获取方式,xhr的升级
- 基于Promise实现
- fetch(url).then()
fetch('http://localhost:3000/fdata').then(function(data){
// text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
return data.text();
}).then(function(data){
//在这个then里面我们能拿到最终的数据
console.log(data);
})
(1) fetch API 中的 HTTP 请求
- fetch(url, options).then()
- 在 options 对象中 指定对应的 method:请求使用的方法get,delete,post,update,put
- post 请求的时候 需要在options 中 设置 请求头 headers 和 body
A get参数传递 查询
// 1.1 传统URL-通过url ? 的形式传参
fetch('http://localhost:3000/books?id=123', {
//get 请求可以省略不写 默认的就是GET
method: 'get'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
// 1.2 restful形式的URL-通过/ 的形式传递参数
fetch('http://localhost:3000/books/456', {
method: 'get'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
B delete请求方式参数传递 删除id 是 id=789
// 删除id 是 id=789
fetch('http://localhost:3000/books/789', {
method: 'delete'
})
.then(function(data) {
return data.text();
}).then(function(data) {
console.log(data)
});
C post请求传参
//1.1 传统的表单格式数据
fetch('http://localhost:3000/books', {
method: 'post',
// 3.1 传递数据
body: 'uname=lisi&pwd=123',
// 3.2 设置请求头
headers: {
//传统的表单格式
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function(data) {
return data.text();
}).then(function(data) {
console.log(data)
});
//1.2 json格式数据
fetch('http://localhost:3000/books', {
method: 'post',
//JSON.stringify()将对象或数组的值转换为 JSON 字符串
body: JSON.stringify({
uname: '张三',
pwd: '456'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data) {
return data.text();
}).then(function(data) {
console.log(data)
});
D put请求传参 修改id 是 123 的
fetch('http://localhost:3000/books/123', {
method: 'put',
body: JSON.stringify({
uname: '张三',
pwd: '789'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data) {
return data.text();
}).then(function(data) {
console.log(data)
});
(2) fetchAPI 中 响应格式
- data.text()
- data.json()
fetch('http://localhost:3000/json').then(function(data){
// return data.json(); // 将获取到的数据使用 json 转换对象
return data.text(); // // 将获取到的数据 转换成字符串
}).then(function(data){
// console.log(data.uname)
// console.log(typeof data)
var obj = JSON.parse(data);
console.log(obj.uname,obj.age,obj.gender)
})
axios
基于promise用于浏览器和node.js的http客户端
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 自动转换JSON数据
(1)基本用法
<script type="text/javascript" src="js/axios.js"></script>
<script type="text/javascript">
axios.get('http://localhost:3000/axios').then(function(ret){
// 注意data属性是固定的用法,用于获取后台的实际数据
// console.log(ret.data)
console.log(ret)
})
</script>
(2)常用API
- get 查询
- delete 删除
- post 添加
- put 修改
A get 请求传递参数
// 1 通过传统的url 以 ? 的形式传递参数
axios.get('http://localhost:3000/axios?id=123').then(function(ret){
console.log(ret.data)
})
// 2 restful 形式传递参数
axios.get('http://localhost:3000/axios/123').then(function(ret){
console.log(ret.data)
})
// 3 通过params 形式传递参数
axios.get('http://localhost:3000/axios', {
params: {
id: 789
}
}).then(function(ret){
console.log(ret.data)
})
B delete请求传递参数
axios.delete('http://localhost:3000/axios', {
params: {
id: 111
}
}).then(function(ret){
console.log(ret.data)
})
C post请求传递参数
// 1 通过选项传递参数
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
// 2 通过 URLSearchParams 传递参数
var params = new URLSearchParams();
params.append('uname', 'zhangsan');
params.append('pwd', '111');
axios.post('http://localhost:3000/axios', params).then(function(ret){
console.log(ret.data)
})
D put请求传递参数 和 post 同
axios.put('http://localhost:3000/axios/123', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
async 和 await
- ES7中的语法,更加方便的进行异步操作
- 关键字async用于函数上(async 函数都会隐式返回一个 promise对象)
- 关键字await用于async函数中(await后面可以直接跟一个 Promise实例对象)
async function queryData() {
var ret = await new Promise(function(resolve, reject){
setTimeout(function(){
resolve('nihao')
},1000);
})
// console.log(ret.data)
return ret;
}
queryData().then(function(data){
console.log(data)
})