1
InDom 156 天前
好像没啥难度?
做一个 对象,首先需要一 or 两个锁,然后需要一 or 两个队列。 发起 ajax 需要过一下锁,ajax 发出前锁定,ajax 成功后,锁设置过期时间 2s 。 getD 先检查队列是否能取到,成功就返回,失败就 ajax , 如果发出就等成功,失败就把回调推入等待队列。 ajax 成功后挨个讲结果回调给等待队列。 |
2
shiny 156 天前
这里要考虑一个问题,只有一个进程还是会有多个进程。如果是单进程的,直接用变量就能实现;多进程需要借助其他服务。
PS:你的描述够详细了,ChatGPT 写出来的就已经八九不离十了。 |
3
zbinlin 156 天前
用 async generator 来写试试
|
5
vampuke 156 天前
let pending;
const getId = async() => { if (pending) return pending; pending = new Promise((resolve) => { setTimeout(() => { resolve('id'); setTimeout(() => { pending = null; }, 2000); }, 1000); }); return pending; } |
6
Lhcfl 156 天前
不考虑多线程:
function makeGetD() { let datas = []; let promise = null; let canNext = true; const getD = async () => { if (datas.length > 0) return datas.pop(); if (promise == null) { if (!canNext) return; canNext = false; setTimeout(() => (canNext = true), 2000); promise = new Promise(res => setTimeout(() => { console.log("i'm ajax"); res([1,2,3,4,5,6,7,8,9,10]); }, 300)); } datas = await promise; promise = null; return await getD(); } return getD; } getD = makeGetD(); |
7
Curtion 156 天前
|
8
nbin2008 OP 感谢大家帮忙,没来得及看,用 2 楼的方法解决了
const axios = require('axios'); let dataQueue = []; let isFetching = false; async function fetchData() { if (isFetching) return; isFetching = true; try { const response = await axios.get('https://example.com/api/data'); // 替换为实际的 API 地址 dataQueue = response.data.slice(0, 10); // 假设每次获取 10 条数据 } catch (error) { console.error('Error fetching data:', error); } finally { isFetching = false; } } async function getD() { while (dataQueue.length === 0) { if (!isFetching) { await fetchData(); } await new Promise(resolve => setTimeout(resolve, 100)); // 等待数据获取完成 } return dataQueue.shift(); } // 示例:同时执行 30 次 getD (async () => { const promises = Array.from({ length: 30 }, () => getD()); const results = await Promise.all(promises); console.log(results); })(); |
9
nbin2008 OP |
10
Projection 155 天前
你说的这个用 Streams API 很容易实现:
```js import { setTimeout } from "node:timers/promises"; let id = 0; async function fetchData() { console.log("fetchData()"); await setTimeout(Math.random() * 500); return Array(10) .fill(null) .map(() => ({ id: ++id })); } const stream = new ReadableStream( { async pull(controller) { const data = await fetchData(); for (const a of data) { controller.enqueue(a); } }, }, new CountQueuingStrategy({ highWaterMark: 0 }), // fully lazy ).values(); async function getD() { return (await stream.next()).value; } for (let i = 0; i < 30; i++) { console.log("data", await getD()); } ``` 输出结果: fetchData() data { id: 1 } data { id: 2 } data { id: 3 } data { id: 4 } data { id: 5 } data { id: 6 } data { id: 7 } data { id: 8 } data { id: 9 } data { id: 10 } fetchData() data { id: 11 } data { id: 12 } data { id: 13 } data { id: 14 } data { id: 15 } data { id: 16 } data { id: 17 } data { id: 18 } data { id: 19 } data { id: 20 } fetchData() data { id: 21 } data { id: 22 } data { id: 23 } data { id: 24 } data { id: 25 } data { id: 26 } data { id: 27 } data { id: 28 } data { id: 29 } data { id: 30 } 这里为了定义你所需要 getD() 显得把代码搞复杂了一点,而实际上你可以根据情况使用 for await... of 。 你从 LLM 获得的代码有轮询的部分,所以强烈不推荐: await new Promise(resolve => setTimeout(resolve, 100)); // 等待数据获取完成 |
11
jifengg 155 天前
综合看下来,我自己写的话应该也和 @Curtion 差不多。
你不需要一个 isFetching 来表示是否正在异步获取。如果不是你要求两次间隔 2s ,就根本不需要 setTimeout 当然,实际上你应该还要考虑 接口返回数据量是 0 的情况。 |
13
nbin2008 OP @Projection 感谢,看的不是很懂,api 生疏
|
14
DOLLOR 155 天前
|