写在最前面
问题1?
项目中经常会遇到通过请求获取某个值或者条件后,根据值或者条件去执行其他操作的情况,但往往请求属于异步任务,导致没拿到值或者条件时,就执行了之后的操作,会因为值为空或者条件不满足而导致报错!只能将后续代码写在请求promist.then()中,导致代码不可维护,不灵活,所谓的‘函数瀑布’。
理想状态下:
console.log('执行上一步操作')
alert('请求接口满足了条件')
console.log('根据条件执行下一步操作')打印结果如下
1.执行上一步操作
2.弹出‘请求接口满足了条件’,点击确定
3.根据条件执行下一步操作
现实状态下:
console.log("执行上一步操作");
var sino = null;
new Promise((resolve) => {
setTimeout(() => {
sino = "满足";
resolve(sino);
}, 3000);
}).then(() => {
console.log(`条件${sino}`);
});
console.log(`根据条件${sino}执行下一步操作`);打印结果如下
1.执行上一步操作
2.根据条件null执行下一步操作(后续代码会拿不到条件)
3.等待3秒后打印 条件满足
通常的解决办法:
console.log("执行上一步操作");
var sino = null;
new Promise((resolve) => {
setTimeout(() => {
sino = "满足";
resolve(sino);
}, 3000);
}).then(() => {
console.log(`条件${sino}`);
console.log(`根据条件${sino}执行下一步操作`);
});打印结果如下:
1.执行上一步操作
2.等待3秒后 条件满足
3.根据条件满足执行下一步操作
有没有更好的解决办法?
1.async-await异步请求同步化
2.await后面接一个 new promise函数或者会return new promist的函数并执行它
3.await只能放在async函数里
上代码:
async fn() {
console.log("执行上一步操作");
var sino = null;
sino = await new Promise((resolve) => {
setTimeout(() => {
sino = "满足";
console.log(`${sino}`);
resolve(sino);
}, 3000);
});
console.log(`根据条件${sino}执行下一步操作`);
},
fn()打印结果如下:
1.执行上一步操作
2.满足
3.根据条件 满足 执行下一步操作
封装后:
fetchSino() {
return new Promise((resolve) => {
setTimeout(() => {
let sino = "满足";
console.log(sino);
resolve(sino);
}, 3000);
});
},
async fn() {
console.log("执行上一步操作");
const sino = await this.fetchSino();
console.log(`根据条件${sino}执行下一步操作`);
},
fn()1.执行上一步操作
2.满足
3.根据条件 满足 执行下一步操作
此处需要注意:
扩展 :await 等到之后,做了一件什么事情?
问题1:如果await后面不是promise对象呢
fetchSino() {
let sino = "满足";
console.log(sino);
return sino;
},
async fn() {
console.log("执行1");
const sino = await this.fetchSino();
console.log(`根据条件${sino}执行下一步操作`);
},
fn()
console.log('执行fn后操作')
// 执行1
// 满足
// 执行fn后操作
// 根据条件满足执行下一步操作fn()执行,进入函数内部,遇到await ,去执行后面的函数 ,如果发现该函数不是return new Promist的函数, await都会执行完,让出线程,阻塞后面的代码继续执行,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果。
问题2:如果请求失败或者没有return结果呢?
请求失败:
fetchSino() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let sino = "不满足";
console.log(sino);
reject(sino);
}, 3000);
});
},
async fn() {
console.log("执行上一步操作");
const sino = await this.fetchSino();
console.log(`根据条件${sino}执行下一步操作`);
},
fn()
// 执行上一步操作
// 不满足
// Uncaught (in promise) 不满足
// 后面就没有打印任何东西没有return结果:
fetchSino() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let sino = "不满足";
console.log(sino);
}, 3000);
});
},
async fn() {
console.log("执行上一步操作");
const sino = await this.fetchSino();
console.log(`根据条件${sino}执行下一步操作`);
},
fn()
// 执行上一步操作
// 不满足
// 后面就没有打印任何东西await右侧表达式的结果,就是await要等的结果,结果成功返回,继续执行下面的代码,如果没有返回结果或者promise返回失败,对于await来说就是失败了,则会让出线程,阻塞代码,因此在项目中需要运用try catch解决
fetchSino() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let sino = "不满足";
reject(sino);
}, 3000);
});
},
async fn() {
try {
console.log("执行fetchSino");
const sino = await this.fetchSino();
console.log(`根据条件${sino}执行下一步操作`);
} catch (error) {
console.log(error);
console.log(`根据条件不满足操作`);
}
},
fn()
// 执行fetchSino
// 不满足(catch打印)
// 根据条件不满足操作(catch打印)问题3:在axios中如何运用async/await异步请求同步化?
Axios 是一个基于 promise 的 HTTP 库,axios返回的就是一个Promise对象
不多bb,上代码:
async fn() {
try {
let result = await axios.get('/api/survey/list/')
result && console.log('执行请求后的操作')
} catch (err) {
console.log(err)
}
},
fn()写在最后
我们都拥有足够的时间,只是要善加利用。一个人如果不能有效利用有限的时间,就会被时间俘虏,成为时间的奴隶。一旦在时间面前成为弱者,他将永远是一个弱者。因为放弃时间的人,同样也会被时间放弃。
——歌德