Documentation Index
Fetch the complete documentation index at: https://graph-sitter.com/llms.txt
Use this file to discover all available pages before exploring further.
Modern JavaScript/TypeScript codebases often need to migrate from Promise-based code to the more readable async/await syntax. Graph-sitter provides powerful tools to automate this conversion while preserving business logic and handling complex scenarios.
Finding Promise Chains
Graph-sitter offers multiple ways to locate Promise chains in your codebase:
- In files
- In functions
- Part of a function call chain
Promise Chains in a File
Find all Promise chains in a file:
ts_file = codebase.get_file("api_client.ts")
promise_chains = ts_file.promise_chains
print(f"Found {len(promise_chains)} Promise chains")
Promise Chains in a Function
Find Promise chains within a specific function:
ts_func = codebase.get_function("getUserData")
chains = ts_func.promise_chains
for chain in chains:
print(f"Found chain starting with: {chain.name}")
Promise Chain starting from a Function Call
Find Promise chains starting from a specific function call:
# Assuming the function call is part of a promise chain
fetch_call = codebase.get_function("fetchUserData").function_calls[2]
chain = fetch_call.promise_chain
Converting Promise Chains
In-Place Conversion
Convert Promise chains directly in your codebase:
# Find and convert all Promise chains in a file
for chain in typescript_file.promise_chains:
chain.convert_to_async_await()
Handle Business Logic Without In-Place Edit
Generate the transformed code without inplace edit by returning the new code as a string. This is useful when you want to add additional business logic to the overall conversion.
async_await_code = chain.convert_to_async_await(inplace_edit=False)
print("Converted code:", async_await_code)
promise_statement = chain.parent_statement
new_code = promise_statement.edit(
f"""
{async_await_code}
// handle additional business logic here
"""
)
Supported Promise Chain Patterns
- Basic
promise.then() statements of any length
- Catch
promise.then().catch() statements of any length
- Finally
promise.then().catch().finally() statements of any length
- Desctructure
promise.then((var1, var2)) statements -> let [var1, var2] = await statement;
- Implicit returns ->
return promise.then(() => console.log("hello"))
- Top level variable assignments ->
let assigned_var = promise.then()
- Top level variable assignments ->
let assigned_var = promise.then()
- Ambiguous/conditional return blocks
Examples
1. Basic Promise Chains
// Before
function getValue(): Promise<number> {
return Promise.resolve(10)
.then(value => value * 2);
}
Applying the conversion…
promise_chain = codebase.get_function("getValue").promise_chains[0]
promise_chain.convert_to_async_await()
codebase.commit()
// After
async function getValue(): Promise<number> {
let value = await Promise.resolve(10);
return value * 2;
}
2. Error Handling with Catch/Finally
// Before
function processData(): Promise<void> {
return fetchData()
.then(data => processData(data))
.catch(error => {
console.error("Error:", error);
throw error;
})
.finally(() => {
cleanup();
});
}
Applying the conversion…
promise_chain = codebase.get_function("processData").promise_chains[0]
promise_chain.convert_to_async_await()
codebase.commit()
// After
async function processData(): Promise<void> {
try {
let data = await fetchData();
return processData(data);
} catch (error) {
console.error("Error:", error);
throw error;
} finally {
cleanup();
}
}
3. Promise.all with Destructuring
// Before
function getAllUserInfo(userId: number) {
return Promise.all([
fetchUserData(userId),
fetchUserPosts(userId)
]).then(([user, posts]) => {
return { user, posts };
});
}
Applying the conversion…
promise_chain = codebase.get_function("getAllUserInfo").promise_chains[0]
promise_chain.convert_to_async_await()
codebase.commit()
// After
async function getAllUserInfo(userId: number) {
const [user, posts] = await Promise.all([
fetchUserData(userId),
fetchUserPosts(userId)
]);
return { user, posts };
}
4. Handling Ambiguous Returns Using Anonymous functions
For then blocks that have more than one return statement, Graph-sitter will add an anonymous function to handle the ambiguous return to guarantee a deterministic conversion.
// Before
function create(opts: any): Promise<any> {
let qResponse = request(opts);
qResponse = qResponse.then(function success(response) {
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new Error(JSON.stringify(response));
}
if (typeof response.body === "string") {
return JSON.parse(response.body);
}
return response.body;
});
return qResponse;
}
Applying the conversion…
promise_chain = codebase.get_function("create").promise_chains[0]
promise_chain.convert_to_async_await()
codebase.commit()
// After
async function create(opts): Promise<any> {
let qResponse = request(opts);
let response = await qResponse;
qResponse = (async (response) => {
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new Error(JSON.stringify(response));
}
if (typeof response.body === "string") {
return JSON.parse(response.body);
}
return response.body;
})(response);
return qResponse;
}
Handling Top-Level Assignment Variables
When converting Promise chains that involve top-level assignment variables, you can specify the variable name of your choice or pick the default which is the original variable assignment name.
# Convert with custom variable names for clarity
chain.convert_to_async_await(
assignment_variable_name="operationResult",
)
Next Steps
Converting Promise chains to async/await improves code readability and maintainability. Codegen’s tools make this migration process automated and reliable, handling complex cases while preserving business logic.
Here are some next steps to ensure a successful migration:
- Ensure to run
npx prettier --write . after the migration to fix indentation + linting
- Incremental Migration: Convert one module at a time
- Handle Additional Business Logic: Use
.promise_statement.edit() to modify the entire chain and handle external business logic
- If the specific conversion case is not covered, open an issue on the Codegen repository or try to right your own transformation logic using the codegen-sdk