Skip to content

Commit

Permalink
feat: useSamePromise
Browse files Browse the repository at this point in the history
  • Loading branch information
博文 committed Jun 30, 2021
1 parent 8b5840e commit a4976c6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
30 changes: 28 additions & 2 deletions example/components/throttleAsync.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
<li>原文:https://github.com/bowencool/blog/issues/3</li>
</ul>
<button @click="onSubmit">submit(click me quickly)</button>

<ul>
<li>
背景:多个地方需要同一份数据,往往调用(请求)多次。
</li>
<li>需求:执行(请求)一次,返回同一个结果给多个调用方。</li>
</ul>
<button @click="onGet">Get something same(useSamePromise)</button>

</fieldset>
</template>

Expand All @@ -25,17 +34,34 @@ function submitApi(data: object) {
mode: 'cors',
});
}
const throttledApi = throttleAsync(submitApi);
const throttledSubmitApi = throttleAsync(submitApi);
function getApi(keywords: string) {
console.log('fetching', keywords);
const delay = (0.4 + Math.random() * 2).toFixed(3);
return fetch(`https://httpbin.org/delay/${delay}?keywords=${keywords}`, {
method: 'GET',
mode: 'cors',
}).then(() => ({
data: `result for ${keywords}`,
}));
}
const throttledGetApi = throttleAsync(getApi, { useSamePromise: true });
export default defineComponent({
setup() {
return {
async onSubmit() {
await throttledApi({
await throttledSubmitApi({
msg: 'some data to be sent',
});
console.log('submit completed');
},
async onGet() {
const rez = await throttledGetApi('abc');
console.log('fetched', rez);
},
};
},
});
Expand Down
15 changes: 13 additions & 2 deletions src/throttleAsync.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
/**
* @author bowencool<z.bowen66@gmail.com>
* @description 异步节流:上一次的promise完成之前,不会再次触发。
* @param fn
* @param {boolean} [config.useSamePromise] pending期间,使用同一个 Promise 作为结果
*/
export default function throttleAsync<T, P extends any[], R>(
fn: (this: T, ...p: P) => Promise<R>,
{ useSamePromise = false } = {},
) {
let isPending = false;
let theLastPromise: null | Promise<R> = null;
return function asyncThrottled(this: T, ...args: P): Promise<R> {
if (isPending) {
if (useSamePromise && theLastPromise) {
return theLastPromise;
}
return new Promise(() => {});
} else {
isPending = true;
return fn
const ret = fn
.call(this, ...args)
.then((...a1) => {
isPending = false;
theLastPromise = null;
return Promise.resolve(...a1);
})
.catch((...a2) => {
isPending = false;
theLastPromise = null;
return Promise.reject(...a2);
});
theLastPromise = ret;
isPending = true;
return ret;
}
};
}

0 comments on commit a4976c6

Please sign in to comment.