Last active
June 2, 2026 18:28
-
-
Save marcomontalbano/56e6fddac597df71e0c8c1688539e4e4 to your computer and use it in GitHub Desktop.
A Thenable example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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>; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "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