Async/await operasions throw errors when the underlying Promise rejects, halting eexcution of subsequent code. For example:
async function simulateRequest() {
console.log('Request initiated');
const response = await new Promise<string>((resolve, reject) => {
setTimeout(() => reject('Data fetch timeout'), 1200);
});
console.log('Request completed');
}
simulateRequest();
// Outputs only 'Request initiated'
Wrapping each await in try-catch prevents execution stops but adds redundant boilerplate:
async function simulateRequest() {
console.log('Request initiated');
try {
const response = await new Promise<string>((resolve, reject) => {
setTimeout(() => reject('Data fetch timeout'), 1200);
});
console.log(response);
} catch (error) {
console.error(`Error occurred: ${error}`);
}
console.log('Request workflow finished');
}
// Outputs:
// Request initiated
// Error occurred: Data fetch timeout
// Request workflow finished
A cleaner approach adapts the concept of await-to-js, a minimal utility that wraps Promises to return error/result tuples. However, ArkTS currently does not support destructured variable declarations like const [err, data] = ..., so we’ll create a type-safe wrapper class instead.
First, define the utility function and wrapper class in a shared utility file, say PromiseUtils.ets:
// PromiseUtils.ets
class AsyncOutcome<T, E = Error> {
data?: T;
error?: E;
constructor(successData?: T, failureError?: E) {
this.data = successData;
this.error = failureError;
}
}
export function wrapAsync<T, E = Error>(
targetPromise: Promise<T>,
extraErrorInfo?: Record<string, unknown>
): Promise<AsyncOutcome<T, E>> {
return targetPromise
.then((resolvedData: T) => new AsyncOutcome<T, E>(resolvedData))
.catch((caughtError: E) => {
if (extraErrorInfo) {
const combinedError = Object.assign({}, caughtError, extraErrorInfo) as E;
return new AsyncOutcome<T, E>(undefined, combinedError);
}
return new AsyncOutcome<T, E>(undefined, caughtError);
});
}
Use this utility in any ArkTS component or helper file:
import { wrapAsync } from './PromiseUtils';
async function fetchUserData(userId: string) {
console.log('Fetching user profile...');
const outcome = await wrapAsync(
new Promise<string>((resolve, reject) => {
setTimeout(() => {
userId ? resolve(`User ${userId} profile loaded`) : reject('Missing user ID parameter');
}, 800);
}),
{ requestId: 'user-profile-123' }
);
if (outcome.error) {
console.error('Profile fetch failed', outcome.error);
return;
}
console.log('Profile data:', outcome.data);
// Proceed with UI updates or further processing
}
// Test with invalid input
fetchUserData('');
// Test with valid input
fetchUserData('u_98765');