Skip to content

Commit

Permalink
feat: added abort to mutations
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Mar 7, 2021
1 parent fb4ceed commit 5b134f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
30 changes: 24 additions & 6 deletions packages/villus/src/useMutation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ref, Ref, unref } from 'vue-demi';
import { ref, Ref, shallowRef, unref } from 'vue-demi';
import { MaybeReactive, OperationResult, QueryExecutionContext, QueryVariables } from './types';
import { CombinedError, injectWithSelf } from './utils';
import { CombinedError, createAbortController, injectWithSelf } from './utils';
import { VILLUS_CLIENT } from './symbols';
import { Operation } from '../../shared/src';

Expand All @@ -20,18 +20,29 @@ export function useMutation<TData = any, TVars = QueryVariables>(
const isFetching = ref(false);
const isDone = ref(false);
const error: Ref<CombinedError | null> = ref(null);

const abortController = shallowRef<AbortController | undefined>();
function abort() {
abortController.value?.abort();
}
// This is to prevent state mutation for racing requests, basically favoring the very last one
let lastPendingOperation: Promise<OperationResult<TData>> | undefined;
async function execute(variables?: TVars) {
if (lastPendingOperation) {
abort();
}

isFetching.value = true;
abortController.value = createAbortController();
const vars = variables || {};
const pendingExecution = client.executeMutation<TData, TVars>(
{
query,
variables: vars as TVars, // FIXME: fix this casting
},
unref(opts?.context)
{
signal: abortController.value?.signal,
...unref(opts?.context || {}),
}
);

lastPendingOperation = pendingExecution;
Expand All @@ -42,14 +53,21 @@ export function useMutation<TData = any, TVars = QueryVariables>(
return { data: res.data as TData, error: res.error };
}

lastPendingOperation = undefined;
abortController.value = undefined;
if (res.aborted) {
isFetching.value = false;

return res;
}

data.value = res.data;
error.value = res.error;
isDone.value = true;
isFetching.value = false;
lastPendingOperation = undefined;

return { data: data.value, error: error.value };
}

return { data, isFetching, isDone, error, execute };
return { data, isFetching, isDone, error, execute, abort };
}
10 changes: 6 additions & 4 deletions packages/villus/src/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ function useQuery<TData = any, TVars = QueryVariables>(
let lastPendingOperation: Promise<OperationResult<TData>> | undefined;

async function execute(overrideOpts?: Partial<QueryExecutionOpts<TVars>>) {
isFetching.value = true;
const vars = (isRef(variables) ? variables.value : variables) || {};
if (lastPendingOperation) {
abort();
}

isFetching.value = true;
abortController.value = createAbortController();
const vars = (isRef(variables) ? variables.value : variables) || {};
const pendingExecution = client.executeQuery<TData, TVars>(
{
query: isRef(query) ? query.value : query,
Expand All @@ -84,17 +84,19 @@ function useQuery<TData = any, TVars = QueryVariables>(
return { data: res.data as TData, error: res.error };
}

lastPendingOperation = undefined;
abortController.value = undefined;

if (res.aborted) {
isFetching.value = false;

return res;
}

data.value = res.data as TData;
error.value = res.error;
isDone.value = true;
isFetching.value = false;
lastPendingOperation = undefined;
abortController.value = undefined;

return { data: data.value, error: error.value };
}
Expand Down

0 comments on commit 5b134f9

Please sign in to comment.