Get Execution's result
Learn how to get executions' results from your API or from a workflow.
Prerequisites
Defer provides 2 approaches to get an execution's result: using an execution ID with getExecution(id)
or using awaitResult(fn)
(from a workflow).
Get Execution's result from your API
Calling a background function returns an execution ID, as follows:
import { helloLongTask } from "../defer/helloLongTask";
const { id: executionID } = await helloLongTask()
What await
is waiting for?
Calling a background function needs to done using await
.
Here, await
will not wait for its execution to be done.
await
will return when the execution is received on our side, which is very quick (under 20ms avg)
The return execution ID can later be used (for example, from another route of your API) to query the status of an execution.
Here is a Next.js example:
import { getExecution } from "@defer/client";
import { helloLongTask } from "../defer/helloLongTask";
export async function GET(
_request: Request,
{ params }: { params: { executionId: string } }
) {
const { id, state, result } = await getExecution(params.executionId);
return new Response(JSON.stringify({ id, state, result }), {
status: 200,
headers: { "Content-type": "application/json" },
});
}
What should I do with the execution ID?
You can store an execution ID in your database or directly forward it to your front-end/client that will send it back to your API when polling for the status.
You will find a complete example in our GitHub Profile OpenAI Generator demo (opens in a new tab).
Get parallel executions' results, from a workflow
Defer provides another powerful way to get executions' result.
However, please note that this approach should only be used in a workflow, not from your application.
The @defer/client
exposes a awaitResult()
helper to transform a call to a background function into an asynchronous call, waiting for a result.
For example, you want to implement a workflow that needs to process data in parallel chunks, as follows:
import { awaitResult, defer } from "@defer/client"
import computeChunk from './computeChunk'
// create a version of `computeChunk()` that waits for result
const computeChunkWithResult = awaitResult(computeChunk)
async function processData(chunks: any[]) {
const results = await Promise.allSettled([
// each `computeChunkWithResult()` will return a promise of an execution running in parallel
chunks.map(chunk => computeChunkWithResult(chunk))
])
// `results` is an array of all `computeChunkWithResult()` return values
results
// ...
}
export default defer(processData)
awaitResult(fn)
return a new version of your background function that will await for the execution's final state (success or failed).
By returning a Promise, this pattern enables you to leverage the native Promise API and Promise-based libraries.
import { awaitResult, defer } from "@defer/client"
import computeChunk from './computeChunk'
// create a version of `computeChunk()` that waits for result
const computeChunkWithResult = awaitResult(computeChunk)
const chunk = /* ... */;
const returnedValue = await computeChunkWithResult(chunk)
What happen when an execution fails?
An execution failures will result by a rejection thrown by awaitResult()
- like regular Promises.
When used with await
, an execution failure will raise an exception.