Skip to content

Commit

Permalink
feat(add): async programming
Browse files Browse the repository at this point in the history
  • Loading branch information
seognil committed Apr 11, 2020
1 parent 987d8e0 commit 251c931
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 0 deletions.
39 changes: 39 additions & 0 deletions js/async-programming/parallel/parallel-limit-version-2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { delay } from '../util/delay';

type AsyncFunction = () => Promise<unknown>;
const limitOf = (max: number) => {
const mq: AsyncFunction[] = [];
let count = 0;

const runTask = async () => {
if (count < max) {
count++;
await mq.shift()!();
count--;
checkMq();
}
};

const checkMq = () => {
if (mq.length) runTask();
};

return (fn: AsyncFunction) => {
mq.push(fn);
checkMq();
};
};

// * ================================================================================

const limit = limitOf(2);

console.warn('start');

for (let i = 1; i < 10; i++) {
limit(async () => {
await delay(500);
// await delay(Math.random() * 500 + 100);
console.warn(i);
});
}
30 changes: 30 additions & 0 deletions js/async-programming/parallel/parallel-limit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { delay } from '../util/delay';

type AsyncFunction = () => Promise<unknown>;

const limitOf = (max: number) => {
const mq: AsyncFunction[] = [];
let count = 0;

const runTask = async (fn: AsyncFunction) => {
count++;
await fn();
count--;
if (mq.length) runTask(mq.shift()!);
};

return (fn: AsyncFunction) => {
count < max ? runTask(fn) : mq.push(fn);
};
};

// * ================================================================================

const limit = limitOf(2);

for (let i = 1; i < 10; i++) {
limit(async () => {
await delay(500);
console.warn(i);
});
}
47 changes: 47 additions & 0 deletions js/async-programming/single-lock/key-lock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// * 也可以改成 Map<string, Promise<void>[]>,数组的形式,当最后一个任务完成后(manualRes 调用时)删除 key,以便节约内存
const chainMap = new Map<string, Promise<void>>();

const keyLock = async (key: string) => {
if (!chainMap.get(key)) chainMap.set(key, Promise.resolve());
const chain = chainMap.get(key)!;

let prevPromise = chain;

// * 将 resolve 提到外部,以便实现手动触发
let waitingRes: Function;
let nextPromise = new Promise<void>((res) => {
waitingRes = res;
});

chainMap.set(
key,
chain.then(() => nextPromise),
);

await prevPromise;

return waitingRes!;
};

// * ================================================================================

import { delay } from '../util/delay';

async function process(key: string, msg?: string) {
let release = await keyLock(key);
console.log('get locker', key, msg);

await delay(1000);

console.log('end locker', key, msg);
release();
}

process('key1', 'dog');
process('key1', 'cat');
process('key2', 'Macbook');
// process('key3', 'JavaScript');
// process('key3', 'TypeScript');
// process('key3', 'ClojureScript');
// process('key3', 'Rust');
// process('key3', 'Haskell');
39 changes: 39 additions & 0 deletions js/async-programming/single-lock/single-lock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// * 也可以做成高阶函数,以便生成多个 lock 独立运作

let chain = Promise.resolve();

export const singleLock = async () => {
let prevPromise = chain;

// * 将 resolve 提到外部,以便实现手动触发
let manualRes: Function;
let nextPromise = new Promise<void>((res) => {
manualRes = res;
});

chain = chain.then(() => nextPromise);

await prevPromise;

return manualRes!;
};

// * ================================================================================

import { delay } from '../util/delay';

async function process(msg: string) {
let release = await singleLock();
console.log('get locker', msg);

await delay(1000);

console.log('end locker', msg);
release();
}

process('JavaScript');
process('TypeScript');
process('ClojureScript');
process('Rust');
process('Haskell');
11 changes: 11 additions & 0 deletions js/async-programming/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "CommonJS",
"esModuleInterop": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"strict": true,
"allowJs": true
},
}
1 change: 1 addition & 0 deletions js/async-programming/util/delay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const delay = (ms: number = 100) => new Promise((res) => setTimeout(res, ms));

0 comments on commit 251c931

Please sign in to comment.