咱们平时在遇到不少比较怪异的事情的时候,咱们会使用setTimeout
这样的奇淫异技,好比避免执行的太快了,某些数据尚未来等,我以前基本不用这个,可是在最近的一个项目中用到了。 项目大体是这样的,用的element-ui的el-upload来实现图片上传,就是一个弹框,里面有不少tab页,每一个tab也都有el-upload,只是能每一个上传的参数和地址什么的是不一样的。javascript
<div>操做类型</div>
<el-radio
v-model="currentSelect"
v-for="(item, index) in configs"
:label="index"
:key="'operateRadio' + index"
>{{ item.label }}
</el-radio>
<el-upload :data="data" :action="url" :auto-upload="false" ref="elUpload">
<el-button type="primary" size="small" @click="submit">上传文件</el-button>
</el-upload>
props:[''configs"]
data(){
data: "",
url: "",
currentSelect: 0,
},
computed: {
config() {
return this.configs[this.currentSelect] || {};
},
},
methods: {
submit(){
this.data = this.config.data;
this.url = this.config.url;
console.log(this.data, this.url);
this.$refs.elUpload.submit();
}
}
复制代码
当时的问题是,每次在用户点击切换了操做模式后点击上传没有问题,若是不点的话用(默认的第一种)通常也没有问题,只是偶尔会出现传递给el-upload的data
参数再上传时没有传递给action
的接口地址的状况, 可是在用在调用this.$refs.elUpload.submit();
上传以前打印console.log(this.data, this.url);
确实值已经打印了,他们的指都是字符串,不存在console
打印“不许”的状况。最后解决这个办法就是用了setTimeout
:html
this.data = this.config.data;
this.url = this.config.url;
setTimeout(() => {
this.$refs.elUpload.submit();
}, 200);
复制代码
感受多是el-upload监听prop的变化不及时,或者watch
时没有用相似immediate: true,
之类的吧。前端
如今你们通常都知道一些事件队列的知识,好比setTimeout
是属于宏队列,Promise
是微队列。周五就看到有同事写了相似这样的代码:java
const arr = []
list.forEach(async item => {
const res = await axios.post(item.url);
arr.push(res.data.time);
})
setTimeout(() => {
console.log('arr ', arr);
}, 1000);
复制代码
而后在arr里面有时取不到值跑过来问我,我问他为何这么写,而后他就给我说了宏队列、微队列那一套,还跟我说什么用async
await
把异步变成同步了。。。ios
而后我让他用Promise.all
来写express
const arr = await Promise.all(list.map(item => axios.post(item.url))).map(item => item.data.time);
console.log('arr ', arr);
复制代码
这样确定没问题的。element-ui
我顺便写了个demo让他完全明白,本身的那种setTimeout
骚操做是多么的不靠谱 先用express写个后端接口axios
// server.js
const app = require('express')();
app.post('*', (req, res, next) => {
setTimeout(() => {
res.send({
post: Date.now()
});
}, 4000)
});
app.listen(3000);
复制代码
客户端代码以下:后端
// client.js
const result = [];
list.forEach(async item => {
const res = await axios.post('http://localhost:3000/post');
result.push(res.data.time);
})
setTimeout(() => {
console.log('执行settimeout', result);
}, 600);
console.log('同步', result);
复制代码
执行结果以下bash
同步 []
执行settimeout []
接口数据 1551629543195
接口数据 1551629543195
复制代码
细心的读者可能看到上面两个setTimeout的时间了,后端接口是4000毫秒,前端这边是600毫秒,这种状况下,前端的setTimeout是百分之百拿不到数据的,若是前端把600改为6000就能够拿到了。
同步 []
接口数据 1551629811109
接口数据 1551629811111
执行settimeout [ 1551629811109, 1551629811111 ]
复制代码
可是实际状况能这样用吗?确定不行,你怎么知道接口大概多久能返回接口,这不是胡闹吗?
写累了,开始总结吧。 首先是在同一个事件循环里面微队列永远在宏队列前面执行,async
await
只是把异步的行为用同步的写法写出来,而非是把异步变成同步,这样更符合咱们的同步思惟罢了。