知识点补充
-
对象.then/success:
请求成功
对象.catch
:请求失败 -
当两个都是resolve时返回resolve的值,如果有reject,返回第一个reject的值
promise
promise
对象相当容器 ,产生的结果是异步结果 ,里面封装的是异步编程- 使用:
resolve reject
为两个回调函数,分别在成功和失败时返回
/*1.promise*/
let promise=new Promise(function (resolve,reject) {
if(true){
resolve("这里是之后的后台数据");
}
else{
reject("请求失败");
}
});
promise.then(function (res) {
console.log(res);
},function(err){
console.log(err);
});
- 如果其中有定时器,请求成功后的数据返回可以作为计时器的第三个参数
let promise=new Promise(function (resolve,reject) {
setTimeout(resolve,1000,"data");
});
promise.then(function(res){
console.log(res);//data
})
- 如果要检测异常,则需要使用
catch
语句处理异常;
一个promise
只能处理一个请求(只能处理一个异步请求)
let promise=new Promise(function (resolve,reject) {
try{
if(true){
setTimeout(resolve,1000,"data");
}
else{
throw new Error("数据请求失败");
}
}
catch(err){
reject(err);
}
});
promise.then(function(res){
console.log(res);//data
}).catch(function (err) {
console.log(err);
})
promise
对象的执行顺序
原理:异步请求内部的数据在外面也能拿到
let data=null;
let promise=new Promise(function (resolve,reject){
console.log("start-1");
setTimeout(resolve,300,"内部的数据-4")
});
console.log("外部-2");
promise.then(function (res){
console.log(res);
data=res;
});
console.log("外部结束-3");
console.log(data);// null-5
- 异步加载图片
/*3.图片异步加载*/
let promise = new Promise(function (reslove, reject) {
let img = new Image();
img.src = "./img/baidu.png";
img.onload = function () {
setTimeout(reslove,500,img);
};
img.onerror = function (err) {
reject(new Error("图片加载失败!"))
};
});
promise.then(function (res) {
console.log(res);//reslove
}).catch(function (err) {
console.log(err);
})
7. 原生ajax promise
封装(将五步法写在promise
中并在最后return
一个promise
对象)
const post = function (url, data) {
const promise = new Promise(function (resolve, reject) {
let http = new XMLHttpRequest();
let handle = function () {
if (http.readyState != 4) {
return;
}
if (http.status == 200) {
resolve(http.response);
}
else {
reject(new Error("数据请求失败"));
}
}
http.open("post", url);
http.onreadystatechange = handle;
http.responseType = "json";
if (data) {
http.send()
}
else {
http.send();
}
});
return promise;
}
post("stu.json").then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
});
- 多个
promise
连用
const p1 = new Promise(function (resolve, reject) {
setTimeout(resolve, 5000, "第一个数据加载完成");
});
const p2 = new Promise(function (resolve, reject) {
setTimeout(resolve, 1000, p1);
});
p2.then(function (res) {
console.log(res);//p2等待p1结束
})
Promise
的原型,then
和catch
,finally
console.log(Promise.prototype);
(函数的回调函数是他自己的构造函数,其中包含resolve和reject)
Promise.all()
;多个promise对象合并
合并
promise
对象时的返回值没有直接修改p1,而是修改p1点出来的then
方法里面的res
上
.then
会创建一个新的promise
;如果直接点p1=new promise(……).then.catch()
,相当于let p3=p1.then()
,此时输出p1,p3的value
为undefined
没有值;没有拿到then创建的新的promise
的value
值
const p1 = new Promise(function (resolve, reject) {
setTimeout(resolve, 1000, "学生");
}).then(function (res) {
});
console.log(p1);//value:undefined
const p1 = new Promise(function (resolve, reject) {
setTimeout(resolve, 1000, "学生");
});
let p3= p1.then(function (res) {
});
console.log(p3);//[[PromiseValue]]: undefined
因为p1,p3都相当于两个没有value值的新的promise对象,而在rerurn内给一个返回值相当于把then方法内部的新的promise对象的返回值给当前定义的promise对象的value;所以就显示成功
Then方法底层源码:
//promise then的源码
function Promise(fn) {
// ...
this.then = function (onFulfilled, onRejected) {
var self = this;
return new Promise(function (resolve, reject) {
return self.done(function (result) {
if (typeof onFulfilled === 'function') {
try {
return resolve(onFulfilled(result));
} catch (ex) {
return reject(ex);
}
} else {
return resolve(result);
}
}, function (error) {
if (typeof onRejected === 'function') {
try {
return resolve(onRejected(error));
} catch (ex) {
return reject(ex);
}
} else {
return reject(error);
}
});
});
}
}
其中 done方法的源码为:
// done 源码
this.done = function (onFulfilled, onRejected) {
// ensure we are always asynchronous
setTimeout(function () {
handle({
onFulfilled: onFulfilled,
onRejected: onRejected
});
}, 0);
}
例题:
因为
then
返回了一个新的promise
对象,如果下一个then
要使用上一个then(即返回的新的promise
对象),就要return
res;
const p = new Promise(function (resolve, reject) {
setTimeout(resolve, 1000, "数据");
}).then(function (res) {//数据 此时已经新建了一个promise对象
console.log(res);
return res;
}).then(function (res) {
console.log(res);// 数据 输出上一个then新建的promise对象的value值
}).then(function (res) {
console.log(res);// undefined 由于上一个then里面没有return,所以此次拿不到新建promise的value值
});
Async
可以执行多个promise
- 异步函数返回值为promise对象,同样使用then catch finally
function getName() {
const promise = new Promise(function (resolve, reject) {
try {
setTimeout(resolve, 500, "张三");
}
catch (err) {
reject(err)
}
});
return promise;
}
function getSex(){
const promise=new Promise(function (resolve,reject){
try{
setTimeout(resolve,1000,"男");
}
catch(err){
reject(err)
}
});
return promise;
}
//async 异步函数返回值为promise对象 then catch finally
async function getinfo(){
const name= await getName();
const sex=await getSex();
return {
name:name,
sex:sex
};
}
console.log(getinfo());//promise
getinfo().then(function (res){
console.log(res);
});
- 执行顺序:
等待promise
执行完在继续执行
async function times(val,ms){
await gettime(ms);
console.log(val);
}
function gettime(ms){
return new Promise(function (resolve){
setTimeout(resolve,ms);
});
}
times("输出",1000);//1000秒后输出
await
命令后边必须是promise
(可以直接写也可以间接调用函数里返回值为promise)
async function getlocal(){
const number=await new Promise(function (resolve,reject){
try{
setTimeout(resolve,1000,1);
}
catch(err){
reject(err);
}
})
console.log(number);
return number;
}
getlocal();
- 如果await里面有异常(一个或多个),直接将整体放在try中
如果await后边的promise返回rejected 直接抓异常抓整个await
如果多个await之间有继发关系(上一次的await值下一次要用) 就让他们一个一个走
如果他们之间没有关系可以同时触发(设置计时器时间相同)
async function getlocal(){
let number=null;
try{//抓单个异常
number=await new Promise(function (resolve,reject){
try{
setTimeout(resolve,1000,"抓单个异常");
}
catch(err){
reject(err);
}
})
}
catch(err){
throw err.message;
}
return number;
}
getlocal().then(function (res){
console.log(res);
});
async function getlocal(){
try{
let number=await new Promise(function (resolve,reject){
try{
setTimeout(resolve,1000,"多个异常1");
}
catch(err){
reject(err);
}
})
let data=await new Promise(function (resolve,reject){
try{
setTimeout(resolve,2000,"多个异常2");
}
catch(err){
reject(err);
}
})
return {
number:number,
data:data
};
}
catch(err){
console.log(err);
}
}
getlocal().then(function (res){
console.log(res);
});
继发案例:
function getname(){
return new Promise(function (resolve){
setTimeout(resolve,1000,"张三");
})
}
function getsex(name){
return new Promise(function (resolve){
setTimeout(resolve,1000,"男");
})
}
function getage(age){
return new Promise(function (resolve){
setTimeout(resolve,1000,"18");
})
}
async function getinfo(){
let name=await getname();
let age=await getage(name);
let sex=await getage(age);
return sex;
}
getinfo().then(function (res){
console.log(res);
});