异步请求的处理方式
如果自己封装一个网络请求
function requestWeb(url, successCallback, failClaaback) {
//模拟网络请求
setTimeout(() => {
if (url === "mimi") {
//请求成功
let name = ["aa", "bb", "ccc"];
successCallback(name);
} else {
//请求失败
let err = "请求失败";
failClaaback(err);
}
}, 500);
}
//调用
requestWeb(
"mimi",
(res) => {
console.log(res);
(res) => {
(res) => {
//....回调地狱
},
},
},
(err) => {
console.log(err);
}
);
这种回调的方式有很多的弊端:
- 如果是我们自己封装的requestData,那么我们在封装的时候必须要自己设计好回调函数的名称以及想好如何更好的使用
- 如果我们使用的是别人封装的requestData或者一些第三方库,那么我们必须去看别人的源码或者文档,才知道它这个函数需要怎么去获取到结果
- 回调地狱的出现
Promise的基本使用
es6新增的一个API
通过new创建Promise对象时,需要传入一个回调函数我们称之为executor
- 这个回调函数会被立即执行,并且会传入另外两个回调函数
resolve和reject - 当我们调用
resolve回调函数时,会执行Promise对象的then方法传入的回调函数 - 当我们调用
reject回调函数时,会执行Promise对象的catch方法传入的回调函数
// const promise = new Promise((resolve, reject) => {
// resolve(), reject();
// });
function requestWeb(url) {
return new Promise((resolve, reject) => {
//异步请求代码
setTimeout(() => {
if (url === "mimi") {
//请求成功
let name = ["aa", "bb", "ccc"];
resolve(name);
} else {
//请求失败
let err = "错误信息";
reject(err);
}
}, 500);
});
}
const promise = requestWeb("mimi");
promise
.then((res) => {
console.log("请求成功", res);
})
.catch((err) => {
console.log("请求失败", err);
});
Promise的三种状态
-
pending:待定的悬而未决的状态,执行了executor后进入该状态 -
fulfilled:兑现/已敲定状态,调用resolve()后,Promise 的状态更改为 fullfilled -
rejected:拒绝状态,调用reject()后,Promise 的状态更改为 rejected -
fulfilled和rejected状态一旦确定下来就无法更改
new Promise((resolve, reject) => {
// 执行了 executor 后,处于pending状态
setTimeout(() => {
if (true) {
// 调用resolve()后,Promise 的状态更改为 fullfilled,且无法再次更改
resolve("请求成功");
} else {
// 调用reject()后,Promise 的状态更改为 rejected,且无法再次更改
reject("请求失败");
}
}, 500);
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
//打印"请求成功"
Promise的resolve方法参数
- 普通的值或对象
pending-->fulfilled - 传入一个Promise,当前的状态会由传入的Promise来决定
const mimi_promise = new Promise((resolve, reject) => {});
new Promise((resolve, reject) => {
resolve(mimi_promise);
}).then((res) => {
console.log(res);
});
- 传入一个对象且该对象有then方法(对象实现了thenable接口),也会执行该then方法,并且由该 then 方法决定后续的状态
const mimi_promise = new Promise((resolve, reject) => {});
new Promise((resolve, reject) => {
const obj = {
then: function (resolve, reject) {
resolve("resolve message");
},
};
resolve(obj);
}).then((res) => {
console.log(res);
});
Promise的对象方法--then
对象方法和类方法
对象的方法意味着要先new出来一个对象,通过new出来的对象去promise调用promise对象上的方法
const promise = new Promise()
promise.then()
类方法通过类名直接去调用的方法
Promise.all()
then方法是放在Promise的原型上的一个方法:他其实是放在Promise原型上的Promise.prototype.then
同一个Promise可以多次调用then方法
当reslove被回调时,所有的then方法都会被调用
const promise = new Promise((resolve, reject) => {
resolve("hahahah");
});
promise.then((res) => {
console.log(res);
});
promise.then((res) => {
console.log(res);
});
then方法传入的回调函数可以有返回值
- 返回普通值,那么这个普通的值被作为一个新的Promise的resolve值
promise
.then((res) => {
return "aaaa";
})
.then((res) => {
console.log(res);
return "bbbb";
})
.then((res) => {
console.log(res);
});
- 返回Promise,resolve的参数是一个Promise时外层Pormise的状态由里面的Promise状态决定
promise
.then(() => {
return new Promise((resolve) => {
setTimeout(() => {
resolve("请求成功");
}, 2000);
});
})
.then((res) => {
console.log(res);
});
- 如果返回的是一个对象,并且该对象实现了 thenable,该 then 函数有两个参数resolve、reject,则 resolve 的将会传递给下一个 Promise。
promise
.then(() => {
return {
then: (resolve) => {
resolve("1111");
},
};
})
.then((res) => {
console.log(res);
});
其他
axios.get函数返回的是一个promise,所以可以直接
.then.catch
async await 使用的话要用try catch捕获异常
如果有四个网络请求呢,6个呢,那代码是不是全部都是回调函数,难以阅读,并且嵌套过深,这时 我们使用async await优化代码
因为js执行代码是一行一行往下执行,这里发promise111请求时,前面带上await就是为了让写异步代码像写同步代码一样,也是一行一行执行
关键点,也是async await主要作用:为了让写异步代码像写同步代码一样优雅,async await也被称为promise的语法糖
async await两个关键字是一起用的, async 写在函数前面,作用为:把这个函数变成 异步函数。
await后面跟一个promise(如果后面不是promise,会直接把他变成一个promise),作用是:等待后面的promise结果返回