Promise对象
在说promise之前先谈谈异步,前面学习了ajax就是一个异步方法,在ES6之前为了获取异步代码里面的数据用的是回调函数:
function getTi(callback){
setTimeout(function(){
callback('喝茶')
},2000)
}
getTi(function(data){
console.log(data);
})
这里再说下,js是单线程,所以在代码执行过程中,遇到异步代码会先放到队列里面,先执行同步代码,完了回来再执行异步代码(轮循),异步代码谁花费时间短谁会先进入执行待序列,但是有时候我们的一些需求对异步代码是有顺序要求的(与其本身时间无关),代码本身又没有办法自己控制,所以采用下列这种方法来做:
function getTi(callback){
setTimeout(function(){
callback('喝茶')
},2000)
}
function getHuo(back){
setTimeout(function(){
back('吃火锅')
},5000)
}
getHuo(function(data){
console.log(data);
getTi(function(data){
console.log(data);
})
})
这只是两个时间,如果再多几个事情就会造成多重的嵌套,也就是常说的回调地狱,所以ES6新增了promise来解决这个问题
1、promise概念
- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
- 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
- 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
2、promise特点
有且只有这两种,而且一个peomise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般为value,失败的结果数据一般被称为reason
它只有两种状态(PromiseState)可以转化,即
- **操作成功:**pending -> fulfilled/resolved
- **操作失败:**pending -> rejected
实例对象的值:PromiseResult。该对象保存的结果为异步任务成功和失败的结果
- 成功的结果 resolve
- 失败的结果 rejected
代码展示:
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
let n = Math.floor(Math.random()*100);
if (n<=30) {
resolve(n);
} else {
reject(n);
}
})
})
p.then(value=>{
console.log(value);
})
console.log(p);
promise有三个状态:
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
3、promise实现原理
ES6 规定,Promise
对象是一个构造函数,用来生成 Promise
实例。通过在函数内部 return 一个 Promise
对象的实例,这样就可以使用 Promise
的属性和方法进行下一步操作了。
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署
new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve('成功') // 数据处理完成
// reject('失败') // 数据处理出错
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失败
)
promise的方法:then()
方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数.
而 Promise
的优势就在于这个链式调用。我们可以在 then 方法中继续写 Promise
对象并返回,然后继续调用 then
来进行回调操作。
问题一:函数内部的异步函数
var a=(function(){
setTimeOut(()=>'data',1000)
})
怎样才能取得到函数内部的data
1、promise构造函数的参数是个函数
2、该函数的参数有两个:resolve,reject
resolve:异步操作成功,要调用的函数。是then函数的第一个参数
reject表示操作失败,要调用的时候是then函数的第二个参数
var p =new Promise(function(resolve,reject){
异步操作的代码
如果异步操作成功,调用resolve;如果失败,调用reject;
});
方法:then() 可以通过then拿到异步数据
var p = new Promise(function(resolve){ resolve:可以将异步的数据传递出来
resolve('helloworld')
})
p.then(function(data){
consloe.log(data);//hellowrld
}) 拿到异步的数据
function getTea() {
return new Promise(function(resolve){
setTimeout(function () {
resolve('奶茶');
}, 1000)
})
}
function getHotpot(){
return new Promise(function(resolve){
resolve('火锅')
},2000)
}
--------------------------如何先吃火锅再喝奶茶呢?---------------------------------------
getTea().then(function(data){
console.log(data)
return getHotpot();
}).then(function(data){
console.log(data)
})
4、promise的api方法
4.1、.then(callback)
Promise对象含有then方法,then()调用后返回一个Promise对象,意味着实例化后的Promise对象可以进行链式调用,而且这个then()方法可以接收两个函数,一个是处理成功后的函数,一个是处理错误结果的函数。
var promise1 = new Promise(function(resolve, reject) {
// 2秒后置为接收状态
setTimeout(function() {
resolve('success');
}, 2000);
});
promise1.then(function(data) {
console.log(data); // success
}, function(err) {
console.log(err); // 不执行
}).then(function(data) {
// 上一步的then()方法没有返回值
console.log('链式调用:' + data); // 链式调用:undefined
}).then(function(data) {
// ....
});
4.2、.catch(callback)
catch()方法和then()方法一样,都会返回一个新的Promise对象,它主要用于捕获异步操作时出现的异常。因此,我们通常省略then()方法的第二个参数,把错误处理控制权转交给其后面的catch()函数
const p = new Promise((resolve, reject) => {
// 修改p的状态
reject('失败')
})
console.log(p);
p.catch(data => {
console.log(data);
})
4.3、.all()
Promise.all()
Promise包含n个promise的数组,说明:返回一个新的promise,只有promise都成功才成功,只要有一个失败了,就都失败
const p1 = new Promise((resolve, reject) => {
resolve('ok')
})
const p2 = new Promise((resolve, reject) => {
resolve('okhaha')
})
const p3 = new Promise((resolve, reject) => {
resolve('kobab')
})
const result = Promise.all([p1,p2,p3]);
console.log(result);
|| 一真即真
&& 一假即假
4.4 .race()
Promise包含n个promise的数组,说明:返回一个promise,第一个完成的promise的结果状态就是最终的结果状态
const p1 = new Promise((resolve, reject) => {
resolve('ok')
})
const p2 = new Promise((resolve, reject) => {
resolve('jj')
})
const p3 = new Promise((resolve, reject) => {
resolve('ll')
})
const result = Promise.race([p1,p2,p3]);
console.log(result);
5、promise封装ajax
function promise(obj){
return new Promise(function(reslove,reject){
var xhr=new XMLHttpRequest();
if(obj.type=='get'||obj.type=='GET'){
xhr.open(obj.type,obj.url+'?'+setstr(obj.data),obj.async);
xhr.send();
}else if(obj.type=='post'||obj.type=='POST'){
xhr.open(obj.type,obj.url,obj.async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(setstr(obj.data));
}
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
reslove(xhr.responseText);
}else{
reject('错误');
}
}
}
})
}
function setstr(data){//将对象转为字符串
var arr=[];
for(k in data){
arr.push(k+'='+data[k]);
}
return arr.join('&');
}
调用
promise({
type:'get',
url:'text08.php',
async:true,
data:{
a:3,
b:2,
}
}).then(function(data){
console.log(data); return promise({
type:'get',
url:'text09.php',
async:true,
data:{
a:3,
b:2,
}
}).then(function(data){console.log(data)})
})