Skip to content
^finished

如何将异步请求同步化执行?

现在有这么一串代码:

js
import axios from 'axios';
export default {
	methods: {
		GetJoke() {
			let isReturn = '初始值'
			axios.get('https://autumnfish.cn/api/joke').then(res => {
				if (res.data.length > 10) {
					isReturn = true
					console.log('isReturn的值改变了~', isReturn) // true
				}
			})
			console.log(isReturn) // 初始值
		},
	}
}
import axios from 'axios';
export default {
	methods: {
		GetJoke() {
			let isReturn = '初始值'
			axios.get('https://autumnfish.cn/api/joke').then(res => {
				if (res.data.length > 10) {
					isReturn = true
					console.log('isReturn的值改变了~', isReturn) // true
				}
			})
			console.log(isReturn) // 初始值
		},
	}
}

打印结果发现,isReturn的值仍然是"初始值",这是因为接口时异步的,也就是打印isReturn的时候,接口返回值还没获得到。

那么,如何等待接口返回值到达之后,再执行后续代码呢?

在接口中 then() 里return行不行?

js
import { getData } from './xxx/xxx.js'
export default {
    created() {
        console.log(this.confirm()) // promise对象
    },
    methods: {
        confirm(){
            getData().then(res => {
                return true
            })
        }
    }
}
import { getData } from './xxx/xxx.js'
export default {
    created() {
        console.log(this.confirm()) // promise对象
    },
    methods: {
        confirm(){
            getData().then(res => {
                return true
            })
        }
    }
}

打印得到一个promise对象,不行,将接口方法return出去试试:

js
import { getData } from './xxx/xxx.js'
export default {
    created() {
         console.log(this.confirm()) // promise对象
    },
    methods: {
        confirm(){
			return getData().then(res => { // 在这里加上return
			    return true
            })
        }
    }
}
import { getData } from './xxx/xxx.js'
export default {
    created() {
         console.log(this.confirm()) // promise对象
    },
    methods: {
        confirm(){
			return getData().then(res => { // 在这里加上return
			    return true
            })
        }
    }
}

仍然不管用,getData() return出来的结果是一个promise对象。

就算加上了 awaitasync ,抱歉,还是不行。

想要的 ture 在promise对象里面,官方文档里提到了是取不到的,想要等待接口返回值到达后执行后续操作,得将后续代码放到 then() 里面。

看来不能采取return的方案,怎么办?

异步最终解决方案, asyncawait

仅需给methods里的方法和axios方法加上 asyncawait 就可以等接口返回值到达之后再执行后续代码。Option式API的方法格式要改一下。

js
import axios from 'axios';
export default {
	methods: {
		GetJoke: async function() {
			let isReturn = '初始值'
			await axios.get('https://autumnfish.cn/api/joke').then(res => {
				if (res.data.length > 10) {
					isReturn = true
					console.log('isReturn的值改变了~', isReturn) // true
				}
			})
			console.log(isReturn) // true
		},
	}
}
import axios from 'axios';
export default {
	methods: {
		GetJoke: async function() {
			let isReturn = '初始值'
			await axios.get('https://autumnfish.cn/api/joke').then(res => {
				if (res.data.length > 10) {
					isReturn = true
					console.log('isReturn的值改变了~', isReturn) // true
				}
			})
			console.log(isReturn) // true
		},
	}
}

如果在别的接口里调用包裹axios接口的GetJoke()方法,怎么办呢?

给methods中的方法调整一下,给 包裹接口API的方法 前面加上 async,给调用 包裹这个加上async的方法 的方法也加上 async

js
import axios from 'axios';
export default {
	methods: {
		GetJoke: async function () {
			// ...开始
			await axios.get('https://autumnfish.cn/api/joke').then(res => {
				console.log(res)
			})
			// ...其他操作
		},
		waitGetJoke: async function () {
			// ...开始
			await this.GetJoke()
			// ...其他操作
		},
	}
}
import axios from 'axios';
export default {
	methods: {
		GetJoke: async function () {
			// ...开始
			await axios.get('https://autumnfish.cn/api/joke').then(res => {
				console.log(res)
			})
			// ...其他操作
		},
		waitGetJoke: async function () {
			// ...开始
			await this.GetJoke()
			// ...其他操作
		},
	}
}

应用场景有哪些?

比如:我需要以一个数组的每个元素作为参数,循环调用某个接口,当循环到某个接口时,返回值达到了要求的条件,跳出循环

html
<template>
	<div>
		<el-button :loading="loading" type="primary" @click="waitGetJoke()">waitGetJoke</el-button>
	</div>
</template>

<script>
	import axios from 'axios';
	export default {
		data() {
			return {
				isReturn: false,
				loading: false,
			}
		},
		methods: {
			GetJoke: async function() {
				console.log('开始调用接口...')
				await axios.get('https://autumnfish.cn/api/joke').then(res => {
					console.log(res.data.length)
					if (res.data.length > 100) {
						this.isReturn = true
					}
				})
				console.log('...接口调用完毕')
			},
			waitGetJoke: async function() {
				this.isReturn = false
				this.loading = true
				console.log('开始循环...')
				for (let i = 0; i < 10; i++) {
					await this.GetJoke()
					if (this.isReturn) {
						console.log('侦测到长度大于100,break')
						break
					}
				}
				this.loading = false
				console.log('...结束循环')
			},
		}
	}
</script>
<template>
	<div>
		<el-button :loading="loading" type="primary" @click="waitGetJoke()">waitGetJoke</el-button>
	</div>
</template>

<script>
	import axios from 'axios';
	export default {
		data() {
			return {
				isReturn: false,
				loading: false,
			}
		},
		methods: {
			GetJoke: async function() {
				console.log('开始调用接口...')
				await axios.get('https://autumnfish.cn/api/joke').then(res => {
					console.log(res.data.length)
					if (res.data.length > 100) {
						this.isReturn = true
					}
				})
				console.log('...接口调用完毕')
			},
			waitGetJoke: async function() {
				this.isReturn = false
				this.loading = true
				console.log('开始循环...')
				for (let i = 0; i < 10; i++) {
					await this.GetJoke()
					if (this.isReturn) {
						console.log('侦测到长度大于100,break')
						break
					}
				}
				this.loading = false
				console.log('...结束循环')
			},
		}
	}
</script>

同样的,此例可以通过其他方案实现,比如直接在接口的then中跳出循环。但是当业务逻辑更加复杂的时候,放到then中就没那么好实现了。