文章目录
- 一、三个状态
- 二、基本用法
-
- 1.举例
- 2.使用原生Ajax
- 3.图片异步加载(懒加载)
- 三、then()
- 四、Promise.all()
- 五、Promise.race()
- 六、Promise.resolve()
- 七、Promise.reject()
- 八、Generator 函数与 Promise 的结合
异步编程解决方案
一、三个状态
1.promise内部状态 不受外界影响,由异步编程结果决定
pending进行中
fulfilled成功
rejected失败
2.promise中的状态 一旦发生变化不会再修改
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled 和 从pending变为rejected
二、基本用法
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去
1.举例
let promise=new Promise((resolve,reject)=>{
let status=true;
if(status){
resolve('成功');
}
else{
reject(new Error('失败'));
}
})
//promise对象的使用
//写法一
promise.then((res)=>{
//成功回调函数 resolve
console.log(res);
},(error)=>{
console.log(error);
})
//输出: 成功
//写法二
promise.then((res)=>{
//resolve
console.log(res);
}).catch(()=>{
//reject
console.log(error);
}).finally(()=>{
console.log("最终执行的代码");
});
//输出: 成功 最终执行的代码
2.使用原生Ajax
function Ajax(method,url,data,callback){
var http;
if(window.XMLHttpRequest){
http=new XMLHttpRequest();
}
else{
//IE5,IE6
http=new ActiveXObject("Microsoft.XMLHTTP");
}
if(method=="get"){
if(data){
url+="?";
url+=data;
}
http.open(method,url);
http.send();
}
else{
http.open(method,url);
if(data){
http.send(data);
}
else{
http.send();
}
}
http.onreadystatechange= function () {
if(http.readyState==4&&http.status==200){
//匿名函数回调 才能把数据拿到外面使用
callback(http.response);
}
}
}
let promise=new Promise((resolve,reject)=>{
try{
Ajax('get','./city.json',null,(res)=>{
resolve(res);
});
}
catch(e){
reject(e);
}
})
promise.then((res)=>{
//resolve
console.log(res);
}).catch(()=>{
//reject
console.log(error);
}).finally(()=>{
console.log("最终执行的代码");
});
(上面内容即为city.json的全部内容)
3.图片异步加载(懒加载)
异步加载要比同步加载快很多
let promise= function (src) {
return new Promise(function (resolve,reject) {
let image=new Image();
image.onload= function () {
resolve(this); //即image
}
image.onerror= function () {
reject(new Error("图片加载失败"));
}
image.src=src; //相当于给浏览器缓存了一张图片
})
}
let src='./1.jpg'
promise(src).then((img)=>{
console.log(img);
document.body.appendChild(img);
}).catch((error)=>{
console.log(error);
})
三、then()
1.then方法定义在原型对象Promise.prototype上
2.then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。
因此可以采用链式写法,即then方法后面再调用另一个then方法。
let promise=new Promise(function (resolve,reject) {
let data={
json: function () {
return {id:1};
}
}
if(data){
resolve(data);
}
else{
reject(new Error("出错了"));
}
})
promise.then(function (res) {
// console.log(res); //{json: ƒ}
return res.json();
}).then(function (res) {
console.log(res); //{id: 1}
})
四、Promise.all()
将多个 Promise 实例,包装成一个新的 Promise 实例
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
let p1=new Promise((resolve,rejecr)=>{
resolve(1);
});
let p2=new Promise((resolve,rejecr)=>{
resolve(2);
})
let p=Promise.all([p1,p2]);
p.then((result)=>{
console.log(result); // [1, 2]
})
let p1=new Promise((resolve,rejecr)=>{
resolve(1);
});
let p2=new Promise((resolve,rejecr)=>{
reject(new Error("失败"));
})
let p=Promise.all([p1,p2]);
p.then((result)=>{
console.log(result);
}).catch((err)=>{
console.log(err); //Error: 失败
})
五、Promise.race()
同样是将多个 Promise 实例,包装成一个新的 Promise 实例
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
那个率先改变的 Promise 实例的返回值,就传递给p的回调函数
let p1=new Promise((resolve,reject)=>{
//模拟请求 5000ms请求回来的数据
setTimeout(function () {
resolve("数据");
},5000);
});
let p2=new Promise((resolve,reject)=>{
//模拟请求 2s后按超时处理
setTimeout(function () {
reject(new Error("超时"));
},2000);
});
let p=Promise.race([p1,p2]);
p.then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
});
两秒后,p2状态先改变:
六、Promise.resolve()
将现有对象转为一个新的 Promise 对象
Promise.resolve(12);
//等价
new Promise(resolve=>resolve(12));
(1)如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
(2)参数是一个thenable对象(即如果转化对象存在then方法)
会默认执行自身的then方法
let obj={
then: function (resolve) {
resolve(22);
}
}
let p=Promise.resolve(obj);
p.then(function (res) {
console.log(res); //22
})
(3)不是thenable对象
let obj={id:1};
let p=Promise.resolve(obj);
p.then(function (res) {
console.log(res); //{id: 1}
})
七、Promise.reject()
也会返回一个新的 Promise 实例,该实例的状态为rejected
Promise.reject(new Error("失败"));
//等价
new Promise((resolve,reject)=>reject(new Error("失败")))
八、Generator 函数与 Promise 的结合
使用 Generator 函数管理流程,遇到异步操作的时候,通常返回一个Promise对象
let p= function () {
return new Promise(function (resolve) {
setTimeout(function () {
resolve("数据");
},3000)
})
}
let gen= function* (){
try{
let res=yield p();
console.log(res);
}catch(e){
throw e.message;
}
}
function run(Generator){
let it=Generator(); //返回遍历器
function go(result){
if(result.done){
return result.value;
}
return result.value.then(function (res) {
//console.log(res); //数据
return go(it.next(res));
}).catch(function (err) {
it.throw(err);
})
}
go(it.next());
}
run(gen);
//三秒后输出: 数据