场景如下:现在的逻辑是根据后端API的返回数据修改echart的option中的series.data,然后执行setOption方法,渲染图标,但是遇到的问题是,后端API可以正常返回数据,但是根据console的显示是先执行了setOption方法,后执行了API数据赋值给series.data,所以图表渲染不出想要的数据,代码如下
methods: { initChart() { this.chart = echarts.init(document.getElementById(this.id)); fetchOverview().then(response => { console.log('1--') console.log(response.items) console.log('2--') this.option.series[0].data = response.items }).catch(error => { console.log(error); }) console.log('a----') console.log(this.option.series[0].data) console.log('b-----') this.chart.setOption(this.option); }, }
浏览器console输出如下
说明fetchOverview默认是异步执行的,及没有阻塞fetchOverview这个函数后面的内容先执行(所以先输出了a---和b---),而如果要是fetchOverview改成同步执行的话需要使用async和await结合使用
1.async/await场景
这是一个用同步的思维来解决异步问题的方案,当前端接口调用需要等到接口返回值以后渲染页面时。
2.名词解释
async
async的用法,它作为一个关键字放到函数前面,用于表示函数是一个异步函数,因为async就是异步的意思,异步函数也就意味着该函数的执行不会阻塞后面代码的执行,async函数返回的是一个promise 对象。async 函数也是函数,平时我们怎么使用函数就怎么使用它,直接加括号 且 使用 .then的方法(参考https://www.jianshu.com/p/ab767311589d)
await
await的含义为等待。意思就是代码需要等待await后面的函数运行完并且有了返回结果之后,才继续执行下面的代码。这正是同步的效果,那么它在等待什么呢,它后面跟着什么呢?其实它后面可以放任何表达式,不过我们更多放的是一个promise对象的表达式(我立即是.then这种方式执行的)。注意await关键字,只能放在async函数里面!!!
所以修改后的代码如下
methods: { async initChart() { this.chart = echarts.init(document.getElementById(this.id)); await fetchOverview().then(response => { console.log('1--') console.log(response.items) console.log('2--') this.option.series[0].data = response.items }).catch(error => { console.log(error); }) console.log('a----') console.log(this.option.series[0].data) console.log('b-----') this.chart.setOption(this.option); }, }
console输出如下
符合预期!!!
备注:在vue的mount阶段执行的函数都是顺序执行,不会阻塞的,所以如果希望mount阶段的函数也是阻塞的,需要额外写一个async函数,然后把需要同步执行的函数写到里面,然后在mount阶段调用这个额外写的函数,例如
async renderData() { await this.getBusinessLinesAndDepartments() if (this.workFlowData) { // 查看 或 审批流程 _.forEach(JSON.parse(this.workFlowData.workflowSteps), (step) => { if (_.values(step)[0].active) { this.currentStep = _.keys(step)[0] } }) this.form_temp = JSON.parse(this.workFlowData.meta) this.initBusinessLines(false, this.form_temp.department) } else { // 创建流程 this.currentStep = 'apply' } await this.permissionCheck() }, }, mounted() { this.renderData() },
如果写成
mounted() {
this.renderData()
this.permissionCheck() 写成这样,则permissionCheck会先于renderData(会请求后端获取数据)执行
},
报错:Can not use keyword 'await' outside an async function
参考:https://blog.csdn.net/qq_39040192/article/details/94142398
// 注意response 前面的async await searchService(search_key).then(async response => { var service_one_id = response.results[0].id // _.forEach(response.results, (item) => { // service_ids.push(item.id) // }) await deleteService(service_one_id).then(response => { # 如果response前面灭有async,这个await会报错 // 设置新的审批信息变量 _.forEach(workflowSteps, (step) => { var step_name = _.keys(step)[0] var step_info = _.values(step)[0] if (step_name == 'op_approve') { step_info['approve_result'] = true } if (['delete_service', 'end'].includes(step_name)) { // 通过的下一个步骤 step_info['active'] = true } workflowStepsParam.push({[step_name]: step_info}) }) }).catch(error => { workflowStepsParam = workflowSteps console.log(error) }) }).catch(error => { workflowStepsParam = workflowSteps console.log(error) })
参考:
https://www.cnblogs.com/jiangds/p/9139743.html
http://blog.sina.com.cn/s/blog_13d06fc1f0102wzfr.html
https://www.jianshu.com/p/ab767311589d