Vue 数据同步获取

问题场景

vue中,我们像后台请求数据时,使用的是axios,由于请求是需要花费时间的的,而且这个时间还不少(http请求消耗的时间比较长),所以axios发起请求后会立马返回一个Promise对象,然后往下执行js语句。

在Promise对象中进行http请求,请求成功后在.then(callback)中能够拿到请求结果。

let user
console.log('请求前的代码')
this.$http.post('/api/user/get', {Id: '00001'}).then((res) => {
    user = res
    console.log('请求结果:' + res)
})
console.log('请求后的代码,请求结果:' + user)

以上代码,假设获取用户信息需要1s,远大于其他js代码的执行时间,那么最终输出顺序是什么?

请求前的代码
请求后的代码,请求结果:undefined
请求结果:{"Id": "00001", .... }

没错,程序会先执行js代码,而变量赋值在请求成功后,所以我们无法保证在请求外能够拿到请求结果。这是异步非常容易产生的问题。

如果我们的业务逻辑需要请求多个数据,并且后一个请求依赖于前一个请求的结果,这时候我们更不能保证数据获取顺序,因此我们需要将异步请求改成同步,以保证业务逻辑的正确性。

async 与 await

async 意为:异步的,其放在我们所定义的function名前,如:

async getUser() {}

其声明这个函数为一个异步执行的,也就是说 我们调用这个方法时,其返回就是一个Promise对象,显然axios的请求方法,就是通过这个关键字来实现异步的。他的好处就是让程序快速执行,避免用户等待页面加载的时间过长,当然现在我们不想讨论他的优点,他的缺点就是我们现在遇到的问题,我们想要拿到数据再执行下一行代码。

await 意为等待,显然 异步执行的方法,能够通过这个关键字,等待请求结果,实现将异步执行的方法变成同步的。

好了,问题解决,只要在请求时加上await就可以了!

console.log('请求前的代码')
let user = await this.$http.post('/api/user/get', {Id: '00001'})
console.log('请求后的代码,请求结果:' + user)

结果输出:

请求前的代码
请求后的代码,请求结果:{"Id": "00001", .... }

是的,结果确实是正确的,但还有一个规则还没有讲,那就是 async 与 await 必须同时出现 所以我们的代码实际是这样:

asycn getUser() {
    // ... 其他代码
    console.log('请求前的代码')
    let user = await this.$http.post('/api/user/get', {Id: '00001'})
    console.log('请求后的代码,请求结果:' + user)
    // ... 其他代码
}

如果有多个请求需要同步:

asycn getUser() {
    // ... 其他代码
    console.log('请求前的代码')
    let user1 = await this.$http.post('/api/user/get', {Id: '00001'})
    console.log('请求后的代码,请求结果:' + user1)
    let user2 = await this.$http.post('/api/user/get', {Id: '00002'})
    console.log('请求后的代码,请求结果:' + user2)
    let user3 = await this.$http.post('/api/user/get', {Id: '00003'})
    console.log('请求后的代码,请求结果:' + user3)
    // ... 其他代码
    
    return [user1, user2, user3] // 假设返回一个数组
}

如果还要嵌套一层

asycn getUser(){
    ...
},
async getDep(users) {
    let dep1 = await this.$http.post('/api/dep/get', {Id: users[0].DepId})
    let dep2 = await this.$http.post('/api/dep/get', {Id: users[1].DepId})
    let dep3 = await this.$http.post('/api/dep/get', {Id: users[2].DepId})
    return [dep1, dep2, dep3]
},
async getData() {
    let users = await getUser()
    let deps = await getDep(users)
    // ... 其他代码
}

Vue中使用

vue项目中,需要使用到同步的,通常也只有页面渲染时的数据初始化。

我们可以定义一个异步方法,将需要同步的请求都放到其中执行

export default {
    mouted () {
        this.initData()  
    },
    methods: {
        async initData() {
            let users = await getUsers()
            await getDeps(users)
        },
        async getUsers() {
            ...
        },
        async getDeps(user) {
            ...
        },
            
        // ...
    }
}

钩子mouted由于不能使用await,所以需要定义一个异步的initData()方法进行数据的初始化。

我可能啥都不会,希望朋友点评......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容