Last active
July 25, 2023 16:09
-
-
Save zjkuang/5e86fec7a691584a13ee19e9db3cdc9a to your computer and use it in GitHub Desktop.
This file contains 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
// TypeScript Playground - https://www.typescriptlang.org/play | |
//////////////////////////////////////////////////////////////////////////////// | |
// Start multiple promises simultaneously and execute them in parallel | |
const p1 = new Promise((resolve) => { | |
setTimeout(() => { | |
const result = Date(); | |
console.log(`r1: ${result}`); | |
resolve(result); | |
}, 1000); | |
}); | |
const p2 = new Promise((resolve) => { | |
setTimeout(() => { | |
const result = Date(); | |
console.log(`r2: ${result}`); | |
resolve(result); | |
}, 2000); | |
}); | |
const p3 = new Promise((resolve) => { | |
setTimeout(() => { | |
const result = Date(); | |
console.log(`r3: ${result}`); | |
resolve(result); | |
}, 3000); | |
}); | |
// Start all simultaneously | |
const p123 = Promise.all([p1, p2, p3]) | |
.then(([r1, r2, r3]) => { | |
// The following 2 lines of console.log can verify that p1, p2, p3 were executed in parallel (not sequentially) | |
console.log(`[r1, r2, r3]: ${JSON.stringify([r1, r2, r3])}`); | |
console.log('p123 = Promise.all([p1, p2, p3]): ', Date()); | |
// output of above: | |
// [LOG]: "[r1, r2, r3]: ["Fri Jul 30 2021 13:13:51 GMT-0600 (CST)","Fri Jul 30 2021 13:13:52 GMT-0600 (CST)","Fri Jul 30 2021 13:13:53 GMT-0600 (CST)"]" | |
// [LOG]: "Promise.all: ", "Fri Jul 30 2021 13:13:53 GMT-0600 (CST)" | |
return [r1, r2, r3]; | |
}); | |
// async-await way of parallel execution | |
async function f() { | |
const r123 = await Promise.all([p1, p2, p3]) // await p123; | |
console.log(`r123: ${JSON.stringify(r123)}`); | |
} | |
f(); | |
//////////////////////////////////////////////////////////////////////////////// | |
// Promise.all() example | |
const working: () => Promise<string> = () => { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
resolve('working() completed with success'); | |
}, 1000); | |
}); | |
}; | |
const notWorking: () => Promise<any> = () => { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
reject('notWorking() failed'); | |
}, 2000); | |
}); | |
}; | |
const bothPromises: Promise<any>[] = [ | |
working().then((result) => { | |
return result; | |
}), | |
notWorking().then((result) => { | |
return result; | |
}).catch((reason) => { // If we omit this catch() branch, Promise.all(bothPromises) will never receive result | |
console.log('notWorking() failed'); | |
}), | |
]; | |
Promise.all(bothPromises).then((result) => { | |
console.log('Promise.all(): ', JSON.stringify(result)); | |
}); | |
// Similarly we can have Promise.race(), Promise.any() | |
//////////////////////////////////////////////////////////////////////////////// | |
// An example of throwing a Promise.reject() from .then() | |
function pf(control: number): Promise<number> { | |
return new Promise<number>((resolve, reject) => { | |
setTimeout(() => { | |
if (control >= 0) { | |
resolve(control); | |
} | |
reject(`error code: ${control}`); | |
}, 1000); | |
}); | |
} | |
function test(control: number) { | |
pf(control) | |
.then((result) => { | |
if (result === 0) { | |
return Promise.reject('zero'); | |
} | |
console.log('success'); | |
return result; | |
}) | |
.catch((reason) => { | |
console.log(`failure: ${JSON.stringify(reason)}`); | |
return Promise.reject(reason); | |
}); | |
} | |
test(-1); // rejected directly by pf | |
test(0); // resolved by pf by a reject is thrown by test from pf().then() | |
test(1); // resolved | |
//////////////////////////////////////////////////////////////////////////////// | |
// An example of implementing Promise.any() | |
// We made this because for node version under v15, any() is not available for Promise | |
async function asyncCall1() { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
const message = 'F1: No!'; | |
console.log(message); | |
reject(message); | |
}, 100); | |
}); | |
} | |
async function asyncCall2() { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
const message = 'F2: Yes!'; | |
console.log(message); | |
resolve(message); | |
}, 1000); | |
}); | |
} | |
async function asyncCall3() { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
const message = 'F3: No!'; | |
console.log(message); | |
reject(message); | |
}, 1500); | |
}); | |
} | |
interface FailureRecord { | |
failed?: boolean | undefined; | |
reason?: any; | |
} | |
function anyOfPromises(asyncCalls: (() => Promise<any>)[]): Promise<any> { | |
return new Promise((resolve, reject) => { | |
let fulfilled = false; | |
let failures: FailureRecord[] = Array.from({length: asyncCalls.length}, () => ({})); | |
console.log(`failures: ${JSON.stringify(failures)}`); | |
asyncCalls.forEach((asyncCall, index) => { | |
asyncCall().then((value) => { | |
if (fulfilled) { return; } | |
fulfilled = true; | |
resolve(value); | |
}).catch((reason) => { | |
if (fulfilled) { return; } | |
failures[index] = { | |
failed: true, | |
reason, | |
}; | |
const allFailed = failures.every((v) => Boolean(v.failed)); | |
if (allFailed) { | |
reject({failures}); | |
} | |
}); | |
}); | |
}); | |
} | |
anyOfPromises([asyncCall1, asyncCall2, asyncCall3]).then((v) => { | |
console.log(`Fulfilled. ${JSON.stringify(v)}`); | |
}).catch((reason) => { | |
console.log(`All failed. ${JSON.stringify(reason)}`); | |
}); | |
//////////////////////////////////////////////////////////////////////////////// | |
// Some interesting usage of `await` call | |
const refreshToken = async (tag: string) => { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
const newToken = new Date().toISOString(); | |
console.log(tag, '::', 'new generated:', newToken); | |
resolve(newToken); | |
}, 2000); | |
}); | |
} | |
const test1 = async () => { | |
const p = refreshToken('test1'); | |
const callP = async (tag: string) => { | |
try { | |
const result = await p; | |
console.log(tag, '::', JSON.stringify(result)); | |
} catch (error) { | |
console.log(tag, '::', JSON.stringify(error)); | |
} finally { | |
console.log(tag, '::', 'finally'); | |
} | |
}; | |
callP('1-1'); | |
setTimeout(() => { | |
callP('1-2'); | |
}, 1000); | |
}; | |
const test2 = async () => { | |
const p = refreshToken('test2'); | |
const callP = async (tag: string) => { | |
try { | |
const result = await p; | |
console.log(tag, '::', JSON.stringify(result)); | |
} catch (error) { | |
console.log(tag, '::', JSON.stringify(error)); | |
} finally { | |
console.log(tag, '::', 'finally'); | |
} | |
}; | |
callP('2-1'); | |
setTimeout(() => { | |
callP('2-2'); | |
}, 3000); | |
}; | |
const test3 = async () => { | |
const _p = refreshToken('test3'); | |
}; | |
test1(); | |
test2(); | |
test3(); | |
//////////////////////////////////////////////////////////////////////////////// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment