Skip to content

Instantly share code, notes, and snippets.

@marcomontalbano
Last active June 2, 2026 18:28
Show Gist options
  • Select an option

  • Save marcomontalbano/56e6fddac597df71e0c8c1688539e4e4 to your computer and use it in GitHub Desktop.

Select an option

Save marcomontalbano/56e6fddac597df71e0c8c1688539e4e4 to your computer and use it in GitHub Desktop.
A Thenable example
// Thenable example — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#thenables
// A thenable is any object with a .then() method, making it compatible with await and Promise chains.
// This file demonstrates a practical thenable that wraps fetch() with inspectable requestOptions.
function getUserByID(id: number) {
const requestOptions: RequestOptions = {
method: "GET",
baseURL: "https://jsonplaceholder.typicode.com",
path: `/users/${id}`,
headers: { "Content-Type": "application/json", Accept: "application/json" },
};
return {
requestOptions,
then<TResult = User>(
onfulfilled?: ((value: User) => TResult | PromiseLike<TResult>) | null,
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null,
): PromiseLike<TResult> {
const url = `${requestOptions.baseURL}${requestOptions.path}`;
console.log(`Fetching user ${id}...`);
return fetch(url, {
method: requestOptions.method,
headers: requestOptions.headers,
})
.then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json() as Promise<User>;
})
.then(
(user) => (onfulfilled ? onfulfilled(user) : (user as any)),
(err) => (onrejected ? onrejected(err) : Promise.reject(err)),
);
},
};
}
async function run1() {
console.log("\n\n# Run 1");
const userRequest = getUserByID(1);
console.log("Request options:", userRequest.requestOptions);
}
async function run2() {
console.log("\n\n# Run 2");
const userRequest = getUserByID(1);
console.log("Request options:", userRequest.requestOptions);
const user = await userRequest;
console.log("Resolved:", user);
getUserByID(2)
.then((u) => ({ ...u, name: u.name.toUpperCase() }))
.then((u) => console.log("Chained result:", u));
}
void run1();
void run2();
type User = {
id: number;
name: string;
username: string;
email: string;
address: {
street: string;
suite: string;
city: string;
zipcode: string;
geo: { lat: string; lng: string };
};
phone: string;
website: string;
company: { name: string; catchPhrase: string; bs: string };
};
type RequestOptions = {
method: "GET";
baseURL: string;
path: string;
headers: Record<string, string>;
};
{
"type": "module",
"scripts": {
"start": "node index.ts"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment