请教大家一个问题, js,异步执行
nbin20082024-07-24 15:360
运行环境:nodejs
需求:提供一个方法 getD ,此方法内调用 ajax 接口获取数据,然后对外输出
1 、异步调用,比如会同时执行 30 次 getD
2 、当第一次调用 getD ,方法内没有数据,会从 ajax 拿数据,每次拿 10 条,等待中,当拿到数据后,用一条对外提供
3 、当第二次及后续调用 getD
a 如果有前面(第一次)正在 ajax 中,则等待,当 ajax 请求拿到数据后,第二次及后续的用拿到的数据
b 如果前面没有 ajax 中,则直接使用数据
4 、当 ajax 拿到的数据用完后,重复 2-3 ,但 ajax 每次请求间隔,须相隔 2s
不知道咋写,写出的也不满足,谢谢大家
需求:提供一个方法 getD ,此方法内调用 ajax 接口获取数据,然后对外输出
1 、异步调用,比如会同时执行 30 次 getD
2 、当第一次调用 getD ,方法内没有数据,会从 ajax 拿数据,每次拿 10 条,等待中,当拿到数据后,用一条对外提供
3 、当第二次及后续调用 getD
a 如果有前面(第一次)正在 ajax 中,则等待,当 ajax 请求拿到数据后,第二次及后续的用拿到的数据
b 如果前面没有 ajax 中,则直接使用数据
4 、当 ajax 拿到的数据用完后,重复 2-3 ,但 ajax 每次请求间隔,须相隔 2s
不知道咋写,写出的也不满足,谢谢大家
最新回复 (9)
- InDom4月前引用2楼好像没啥难度?
做一个 对象,首先需要一 or 两个锁,然后需要一 or 两个队列。
发起 ajax 需要过一下锁,ajax 发出前锁定,ajax 成功后,锁设置过期时间 2s 。
getD 先检查队列是否能取到,成功就返回,失败就 ajax , 如果发出就等成功,失败就把回调推入等待队列。
ajax 成功后挨个讲结果回调给等待队列。 - shiny4月前引用3楼这里要考虑一个问题,只有一个进程还是会有多个进程。如果是单进程的,直接用变量就能实现;多进程需要借助其他服务。
PS:你的描述够详细了,ChatGPT 写出来的就已经八九不离十了。 - zbinlin4月前引用4楼用 async generator 来写试试
- nbin2008楼主4月前引用5楼@InDom 谢谢提供的思路,我想想
@shiny 谢谢,单进程 - vampuke4月前引用6楼let pending;
const getId = async() => {
if (pending) return pending;
pending = new Promise((resolve) => {
setTimeout(() => {
resolve('id');
setTimeout(() => {
pending = null;
}, 2000);
}, 1000);
});
return pending;
} - Lhcfl4月前引用7楼不考虑多线程:
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(); - Curtion4月前引用8楼
- nbin2008楼主4月前引用9楼感谢大家帮忙,没来得及看,用 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);
})(); - nbin2008楼主4月前引用10楼@Lhcfl if (!canNext) return; 这里返回,就没有数据了
@Curtion 55 行调用,这里不是并发,整体代码很值得学习
谢谢楼上 v 友们的解答 - 回复请 登录 or 快速注册
nbin2008
主题数 56 | 帖子数 2871 | 注册排名 2 |