跳到主要内容
版本:v3

步骤2-调整响应处理

在上一节的保守请求示例中,我们在 Todo 项的创建、编辑和删除请求响应后调用fetch重新拉取数据刷新的页面,为了能在操作后立即展示结果,我们需要进行以下调整:

  1. 将创建、编辑和删除请求的行为模式设置为silent,它们将会在请求时立即触发成功回调;
  2. 手动更新列表,而不是拉取数据,使用虚拟数据占位服务端的响应数据;
  3. 保存操作记录,用于在刷新页面时进行数据补偿;

设置行为模式

通过配置参数behavior进行设置,可选参数为queuesilentstatic,或者一个返回行为数据的函数实现动态设置行为模式,默认为queue

以下为静态设置 behavior 参数。

useSQRequest(createOrEditTodo, {
behavior: 'silent',
immediate: false
});

以下为动态设置 behavior 参数。

const { send } = useSQRequest(createOrEditTodo, {
// arg参数可通过send函数传入
behavior: arg => {
if (arg === 0) return 'silent';
return 'queue';
},
immediate: false
});

当 behavior 设置为函数时,它将在每次发起请求时被调用,来确定本次请求以哪种行为来处理。

静默队列说明

将 behavior 参数设置为queuesilent后,请求将进入静默队列等待发起请求,默认情况下它们将进入名称为default的队列,你还可以指定其他队列来保存 silentMethod 实例,队列之间互不干扰。

useSQRequest(createOrEditTodo, {
// 指定请求信息进入名称为queue-2的队列中
queue: 'queue-2',
behavior: 'silent',
immediate: false
});

在回调中手动更新列表

在新增/编辑后更新列表

当列表页未被销毁,例如在当前页使用模态框操作,或使用了<keep-alive>(Vue)保留了页面组件,数据还会存在,此时我们使用updateStateEffect来更新列表数据,相比于 alova 导出的updateState,它具有追踪虚拟数据追踪功能,当获取到响应数据后,它将自动追踪列表数据内的虚拟数据,并替换为实际数据。

import { useSQRequest, updateStateEffect } from 'alova/client';
import { createOrEditTodo, todoList } from './api.js';

const { onSuccess } = useSQRequest(createOrEditTodo, {
behavior: 'silent',
immediate: false,

// 在处理列表更新前,需要根据响应数据的结构先构造相同结构的虚拟响应数据
// 例如,在创建 Todo 项时将返回这条数据的 id。
silentDefaultResponse: () => {
return {
id: '--'
};
}
});

onSuccess(({ data, silentMethod }) => {
// 构造列表数据项
const editingItem = {
...detail,

// 当编辑时,使用原id,否则使用响应数据内的id
// 在静默提交时,data.id为虚拟数据,在static行为模式时,data.id为实际的id值
id: id || data.id
};

// 使用updateStateEffect,而不是updateState
updateStateEffect(todoList(), todoListRaw => {
if (id) {
todoListRaw = todoListRaw.map(item => (item.id === id ? editingItem : item));
} else {
todoListRaw.unshift(editingItem);
}
return todoListRaw;
});
});

updateStateEffect 的使用方法与updateState一致

移除后更新列表

import { useSQRequest, updateStateEffect } from 'alova/client';
import { deleteTodo, todoList } from './api.js';

const { loading, data, send, onSuccess } = useSQRequest(deleteTodo, {
immediate: false,
behavior: 'silent'
});

onSuccess(({ args: [deletingId] }) => {
updateStateEffect(todoList(), todoListRaw =>
todoListRaw.filter(item => item.id !== deletingId)
);
});

// 事件回调触发删除请求
const handleDelete = deletingId => {
send(deletingId);
};

保存操作记录

仅仅完成手动更新列表还不够,我们还需要考虑当网络恢复后,当请求队列还存等待中的请求时,此时加载的列表数据还不包括未提交请求的部分,这会让用户造成一定的困惑:

“我明明已经新增了多条数据,为什么列表中没有?”

因此我们需要在成功回调中记录操作,以及相关数据,以便再次加载列表数据时,将未提交的数据手动补偿到列表中,从而让列表数据始终保持最新状态。

保存操作记录也很简单,只需要将相关数据挂载到 silentMethod 实例上,它将随着实例一同被持久化。

创建/编辑成功回调

// ...
onSuccess(({ silentMethod }) => {
// 构造列表数据项
const editingItem = {
...detail,
id: id || data.id
};
// ...
if (silentMethod) {
// 设置名称,以便后续查询
// 如果editingItem.id是虚拟数据将自动转换为它的id
silentMethod.entity.setName('edit' + editingItem.id);
silentMethod.reviewData = {
operate: id ? 'edit' : 'add',
data: editingItem
};
silentMethod.save();
}
});

删除成功回调

// ...
onSuccess(({ args: [deletingId], silentMethod }) => {
// ...
if (silentMethod) {
silentMethod.reviewData = {
operate: 'delete',
data: {
id: deletingId
}
};
silentMethod.save();
}
});

注意事项

  1. onSuccess 回调函数中,只有在queuesilent行为模式下 silentMethod 才有值;
  2. 一般而言,你可以通过silentMethod.a = ...、或silentMethod.b = ...来保存操作记录,但在 typescript 中会报错,因此特别提供了reviewData作为静默提交操作记录的保存属性;
  3. 修改 silentMethod 数据后,需要通过silentMethod.save()来保存修改;

下一步将对静默提交请求设置重试参数。