Promise 的基本用法
Promise是异步编程的一种解决方案,
Promise的优缺点
优点
将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
缺点
1.无法取消,一旦新建就会立即执行,无法中途取消。
先来看看promise的特性
立即执行
var a = new Promise(fuction(resolve,reject){
console.log(1);立即执行
resolve(2);
});
console.log(3);
a.then((res)=>{
console.log(res);
})
// 1 3 2
不可逆性
var a = new Promise(fuction(resolve,reject){
resolve(1);
});
a.then((res)=>{
console.log(res); //1
return res+1;
}).then((res)=>{
console.log(res); //2
}).then((res)=>{
console.log(res); //undefinde 上面的then的回调一定return出去,下面then的回调才能拿到res,不然underfined,更不会回头找第一个then回调return返回值
});
回调异步
var a = new Promise(fuction(resolve,reject){
resolve(1);
});
console.log(2);
a.then((res)=>{
console.log(res);
})
// 2 1
2.如果不设置回调函数,在Promise内抛出的错误不会反映到外部,无法得知目前的进度。
写法
Promise对象有三种状态
1.Pending,Promise对象的初始状态
2.Resolved,任务执行完成且成功的状态
3.Rejected,任务执行完成且失败的状态
ES6 规定,Promise
对象是一个构造函数,用来生成Promise
实例。
下面代码创造了一个Promise
实例。
const Promise = new Promise(function(resolve,reject){
if(###成功###){
resolve(value);
}else{
reject(error);
}
})
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,#作为参数传递出去#;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,#作为参数传递出去#。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
是Promise构造函数后面就可以then下去,promise这个实例化对象就是一个Promise构造函数
promise.then(function(value) {
success//resolve状态的回调
}, function(error) {
failure//reject状态的回调
});
注意:是Promise构造函数后面就可以then下去,
下面来个封装ajax的例子;
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
var baseUrl = "https://api.apiopen.top/";
var xhr = new XMLHttpRequest();
xhr.open("GET", baseUrl + "recommendPoetry");
xhr.send();
xhr.addEventListener("readystatechange", function() {
if(xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
})
//用promise封装ajax请求
function ajaxPromise(_url, type) {
return new Promise(function(resolve, reject) {
//resolve表示请求成功 reject表示请求失败
var xhr = new XMLHttpRequest();
xhr.open(type,_url);//xhr.open(type,_url)规定是请求类型在前,请求地址在后
xhr.send();
xhr.addEventListener("readystatechange", function() {
if(xhr.readyState != 4){
return;
}
if(xhr.readyState == 4 && xhr.status == 200) {
var res = JSON.parse(xhr.responseText);
resolve(res);//请求成功后调用resolve(res)把数据传递出去,通过
// 下面的.then(function(res) {console.log(res);})拿到数据
} else {
reject();//请求失败后reject()
}
})
})
}
//Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
//then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,
//第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。
//这两个函数都接受Promise对象传出的值作为参数。
//写法1
ajaxPromise(baseUrl+"recommendPoetry", "get")
.then(function(res) { //指定resolved成功状态执行的回调函数,在这拿到resolve传递出来的数据
console.log("请求成功");
console.log(res);
}).catch(function(err) {//指定reject失败状态执行的回调函数,在这拿到reject传递出来的数据
console.log("请求失败");
console.log(err);
})
//写法二
ajaxPromise(baseUrl+"recommendPoetry", "get")
.then(function(res) { //resolve(res)就是调用.then后面的函数就是 ;
console.log("请求成功");
},function(err) {
console.log(err);
})
</script>
</body>
</html>
微信ajax例子:
//封装ajax请求
function $request(_url, type, callback, data) {
wx.request({
url: _url, //请求地址
method: type, //请求类型
data, //向后台请求的参数
success(res) { //成功后做的事
callback(res)
}
})
}
//es6
//用promise封装ajax
function promiseAjax(_url, type, data) { //这里不要callback也行
return new Promise(function(resolve, reject) { ////Promise有三种状态(成功,失败,请求的过程),Promise里面接收一个函数 //这个函数有resolve,reject两个参数,分别表示成功回调与失败回调
wx.request({
url: _url,
method: type,
data,
success: (res) => { //成功的回调
resolve(res)
console.log("成功")
},
fail(err) {
reject(err)
console.log("失败") //为甚么不输出
}
})
})
}
调用
//第一种ajax
util.$request("http://120.76.31.111/app/XhlGetSubjectTypeList",
"get",function(res){
console.log(res);
})
//用promise方法请求
util.promiseAjax('http://120.76.31.111/app/XhlGetSubjectTypeList', 'get').then(function (res) {//then:表示等待,等待完之后执行后面的函数
wx.hideLoading();//数据请求成功的时候隐藏loading
console.log("promise");
console.log(res);
wx.showToast({
title: '成功',
//success 显示成功图标,此时 title 文本最多显示 7 个汉字长度
icon: "success",
deration: 3000
})
})
Promise.all和Promise.race区别,和使用场景
一、Pomise.all的使用
常见使用场景 : 多个异步结果合并到一起
Promise.all可以将多个Promise实例包装成一个新的Promise实例。用于将多个Promise实例,包装成一个新的Promise实例。
1.它接受一个数组作为参数。
2.数组可以是Promise对象,也可以是其它值,只有Promise会等待状态改变。
3.当所有的子Promise都完成,该Promise完成,返回值是全部值的数组。
4.如果有任何一个失败,该Promise失败,返回值是第一个失败的子Promise的结果。
Promise.all([p1,p2,p3])
先举例之前我们 如果有多个异步请求,但是最终用户想要得到的是 多个异步结果合并到一起,用之前代码举例
console.log('start');
var result1,result2="";
//settimeout 模拟异步请求1
setTimeout(() => {
result1="ok1"
}, 2000);
//settimeout 模拟异步请求2
setTimeout(() => {
result1="ok2"
}, 3000);
//等待 异步1 异步2结果
var tempInterval= setInterval(()=>{
if(result1&&result2){
console.log('data result ok ,,, clearInterval')
clearInterval(tempInterval);
}
},100)
使用Promise.all来解决 ,上代码
Promise.all可以将多个实例组装成一个新的实例,成功的时候返回一个成功数组,
失败的时候则返回最先被reject失败状态的值
比如当一个页面需要在很多个模块的数据都返回回来时才正常显示,比如当数组里的P1,P2、P3都执行完成时,页面才显示。,否则loading
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promse.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
//值得注意的是,返回的数组结果顺序不会改变,即使P2的返回要比P1的返回快,顺序依然是P1,P3、p2
二、Pomise.race的使用
race是赛跑的意思,也就是说Promise.race([p1, p2, p3])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败
类似于Promise.all() ,区别在于 它有任意一个返回成功后,就算完成,但是 进程不会立即停止
常见使用场景:把异步操作和定时器放到一起,如果定时器先触发,认为超时,告知用户
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 2000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 5000);
})
Promise.race([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
一般用于和定时器绑定,比如将一个请求和一个三秒的定时器包装成Promise实例,加入到race队列中,请求三秒中还没有回应时,给用户一些提示或一些相应的操作。
const promise = new Promise(function(resolve, reject) {
let _resolve;
//resolve是一个方法,该方法可以继续传Promise实例进去,也可以把数据resolve出去
_resolve = resolve;
_resolve(new Promise((resolve, reject) => {
console.log(2)
}));
console.log(resolve)
if (true){
resolve(1);//成功的回调把数据resolve出去,then接收处理
} else {
reject('error');
}
});
promise.then();
补充
const promise = new Promise(function(resolve, reject) {
let _resolve;
//resolve是一个方法,该方法可以继续传Promise实例进去,也可以把数据resolve出去
_resolve = resolve;
_resolve(new Promise((resolve, reject) => {
// console.log(2)
}));
// console.log(resolve)
if(true) {
resolve(1); //成功的回调把数据resolve出去,then接收处理
} else {
reject('error');
}
});
promise.then();
不带有任何参数
Promise.resolve() 会直接返回一个promise((resolve, reject)=>{
}) Promise实例
参数不是具有then方法的对象,或根本就不是对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
//有时需要将现有对象转为 Promise 对象,Promise.resolve方法就起到这个作用。
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
//所以可以
Promise.resolve('foo').then(res=>{
console.log(res)
})
参数是一个thenable对象
thenable对象指的是具有then方法的对象,比如下面这个对象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
//Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
//thenable对象的then方法执行后,对象p1的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42
vuex dispatch的返回值 + Promise commit没有返回值
actions: {
ceshi(state) {
return new Promise((resolve, reject) => {
let a = 1;
console.log(a)
resolve(a)
})
}
},
async ceshi() {
await this.$store.dispatch('ceshi').then(res => {
console.log(res)
});
},
不用then,等同
async ceshi() {
let getInfoResult = await this.$store.dispatch('ceshi')
console.log('getInfoResult', getInfoResult);
},
网友评论