如何让API查询函数等待前一次fetch更新完成后再执行?
我开发了一个单页邮件客户端应用,包含多个邮箱,每个邮箱内的emails以JSON对象形式存储。
用户可通过发送fetch请求调用API完成邮件的发送、删除和归档操作。比如删除邮件时,会通过PUT方法发送fetch请求,将该邮件的deleted属性更新为deleted=true。
同理,展示邮箱内容时,会调用API按指定属性筛选邮件。例如收件箱视图仅显示所有deleted=false且archived=false的邮件。
删除邮件的流程是:先从API请求目标邮件的JSON数据,再将响应传递给delete_email()函数,该函数会发起第二次API请求,把邮件的deleted属性更新为true。
我需要让load_mailbox()函数等待API更新完成后再执行,这样加载收件箱时就不会包含刚删除的邮件。
但目前实现中,load_mailbox('inbox')有时会在delete_email()的API请求完成前就执行,导致删除邮件后首次加载收件箱时,已删除的邮件仍会显示,只有刷新页面后才会消失。delete_email()和load_mailbox()均由click事件触发调用。
fetch(`/emails/${email_id}`) .then(response => response.json()) .then(email => { delete_email(email); load_mailbox('inbox') location.reload(); })
delete_email()
function delete_email(email) { // 如果邮件未被删除,移至垃圾箱 if (email.deleted === false) { fetch(`emails/${email.id}`, { method: 'PUT', body: JSON.stringify({ deleted: true, archived: false }) }) } }
应用@David提供的async解决方案后,仍出现与使用.then()结构时相同的问题。delete_email()的if分支(将邮件从收件箱移至垃圾箱)能正常工作:
async function delete_email(email) { // 如果邮件未被删除,移至垃圾箱 if (email.deleted === false) { await fetch(`emails/${email.id}`, { method: 'PUT', body: JSON.stringify({ deleted: true, archived: false }) }) }
但else分支(将邮件从垃圾箱移回收件箱,仅deleted=false的差异)会导致首次加载收件箱时出现重复邮件,刷新页面后才会正确显示:
// 如果邮件在垃圾箱,移回收件箱 else { await fetch(`emails/${email.id}`, { method: 'PUT', body: JSON.stringify({ deleted: false, archived: false }) }) } }
以下是使用David提供的async版本的完整调用代码:
async function get_email() { const response = await fetch(`/emails/${email_id}`); const email = await response.json(); return email } get_email().then(async (email) => { await delete_email(email); load_mailbox('inbox'); })
我查阅过很多类似问题,但无法适配到自身场景:
- 使用
setTimeout()延迟执行后续代码 - 使用
async函数作为调用者等待异步操作完成 - 按顺序调用多个
async函数 - 解决
fetch请求未完成函数就返回的问题 - 使用匿名
.then()确保在fetch完成后调用方法
内容的提问来源于stack exchange,提问作者DAK

