promise对象,一种异步编程解决方案
我们知道,异步操作通常滞后于同步操作且异步操作没有次序性。这在我们编程的过程中,经常会因为异步操作的处理而出现各种稀奇古怪的问题。而ECMAscript提供的promise对象,可以将异步操作以同步操作的流程表现出来,避免了层层嵌套的回调函数。
Promise对象的特点
- 对象的状态不受外界影响。一个promise对象就代表一个异步操作。当对象的状态被确定,就不会改变
- promise对象的三种状态:
- pending: 初始状态,不是成功或失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
只有异步操作的结果才可以决定promise对象的状态,其他任何操作都不可以改变。
- promise对象的三种状态:
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
promise对象的优缺点
- 有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
- Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
promise对象的创建
我们通过构造函数来创建一个promise对象
var myPro = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});
Promise 构造函数包含一个参数,一个带有两个参数的( resolve(解析)和 reject(拒绝))回调,在该回调中执行一系列异步操作。如果异步操作执行成功调用resolve,否则调用reject。
- 实例
//创建一个返回值为promise对象的方法
let myPro(url) =>{return new Promise(function(resolve, reject) {
//创建Ajax对象
var xhr=new XMLHttpRequest();
xhr.open('get',url);
xhr.send();
xhr.οnlοad=()=>{
if(xhr.status===200){
resolve(JSON.parse(xhr.responseText))
}else{
reject(new Error('请求出错了'))
}}
})}
//promise实例
myPro('http://localhost:3008/posts').then((res)=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
- 一般来讲,异步操作成功的时候我们调用resolve方法,否则调用reject方法。then方法接收的就是resolve方法的回调,resolve方法所抛出的参数由then方法接收并处理。resolve方法通常都是抛出一个Error对象,由catch方法接收并输出或处理。
- 除了正常值以外,resolve方法还可以抛出一个promise对象。讲一个promise对象以参数方式抛出。实现链式的异步操作。
// 连续发送请求。
let getPost=(url)=>{return new Promise((resolve,reject)=>{
var xhr=new XMLHttpRequest();
xhr.open('get',url);
xhr.send();
xhr.οnlοad=()=>{
if(xhr.status===200){
resolve(JSON.parse(xhr.responseText))
}else{
reject(new Error('请求出错了'))
}
}
})}
getPost('http://localhost:3008/posts?id=1').then((res)=>{
console.log(res[0].author);
return getPost('http://localhost:3008/posts?id=2')
}).catch(err=>{
console.log(err);
}).then(res=>{
console.log(res[0].author);
return getPost('http://localhost:3008/posts?id=3')
}).catch(err=>{
console.log(err);
}).then(res=>{
console.log(res[0].author);
}).finally(()=>{
console.log("异步最后一步执行");
})
- Promise.all方法
返回所有resolve的集合,必须是所有的异步都返回resolve才能执行。否则执行reject
let Pall=Promise.all( [getPost('http://localhost:3008/posts?id=1'), getPost('http://localhost:3008/posts?id=2'), getPost('http://localhost:3008/posts?id=3')])
Pall.then(arr=>{
console.log(arr);
})
返回所有resolve的集合,必须是所有的异步都返回resolve才能执行。否则执行reject
- Promise.race 方法
let Pall=Promise.race( [getPost('http://localhost:3008/posts?id=1'), getPost('http://localhost:3008/posts?id=2'), getPost('http://localhost:3008/posts?id=3')])
Pall.then(arr=>{
console.log(arr);
})
上面代码中,只要3个异步对象之中有一个实例率先改变状态,Pall的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给Pall的返回值。
- Promise.resolve 方法,将现有异步对象转化为promise对象
var p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
async和await
async 是 ES7 才有的与异步操作有关的关键字,和 Promise , Generator 有很大关联的。
- async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
- await后面接一个会return new promise的函数并执行它
- await只能放在async函数里
const getPost=async()=>{
const res=await axios.get('http://localhost:3008/posts')
// console.log(res.data);
//return 返回值将被作为then的参数
return res.data
}
getPost().then(res=>{
console.log(res);
})