标签导航:

async/await 和 .then 中如何确保所有异步操作完成后再执行后续步骤?

巧妙运用异步操作:确保所有异步任务完成后再执行后续步骤

在使用 async/await 和 .then 处理异步操作时,如何确保所有异步任务完成后再执行后续步骤是一个常见挑战。本文将通过一个实际案例,详细讲解如何解决这个问题。

问题描述: 父组件循环调用子组件的 initfilepath 方法,该方法内部使用 async/await 进行网络请求和图片加载,并使用 .then 处理加载后的图片。由于 async/await 的特性,父组件的循环会继续执行,而不会等待所有子组件的异步操作(包括 dealimagedata 方法中的 Promise.all)完成。因此,需要一种机制来确保所有异步操作完成后,再执行后续操作。

原始代码: 父组件使用 forEach 循环调用子组件的 initfilepath 方法:

this.identifyfailed.forEach((alarm: Alarm, index: number) => {
    this.$nextTick(() => {
        this.$refs['slideimagefaildref'][index].initfilepath(alarm.id)
    })
})

子组件的 initfilepath 方法和 dealimagedata 方法:

async initfilepath(alarmid) {
    // ... 省略部分代码 ...
    await this.dealimagedata(data)
}

async dealimagedata(data, id = 'alarmid') {
    // ... 省略部分代码 ...
    let promiselist = Promise.all(this.imagepaths.map(async (path) => {
        return this.loadimgaepath(path)
    }))
    await promiselist.then(async (data: any) => {
        // ... 省略部分代码 ...
    })
}

问题在于,forEach 循环是同步的,它不会等待 initfilepath 方法(以及其中的异步操作)执行完毕。

解决方案: 为了等待所有子组件的 initfilepath 方法执行完毕,我们需要使用 Promise.all。修改后的父组件代码如下:

const initPromises = this.identifyFailed.map(async (alarm: Alarm, index: number) => {
    await this.$nextTick()
    return await this.$refs['slideImageFaildRef'][index].initFilePath(alarm.id)
})

Promise.all(initPromises).then(() => {
    // 所有子组件的 initFilePath 方法都执行完毕后执行的代码
});

通过 map 方法将每个子组件的 initfilepath 方法调用包装成一个 Promise,然后使用 Promise.all 等待所有 Promise 都 resolve 后,再执行 .then 中的代码。 await this.$nextTick() 确保 DOM 更新完毕后再执行 initfilepath 方法。 这保证了所有异步操作完成后,父组件才能继续执行后续操作。