JS 多次请求 如何使后者覆盖前者

2022-08-18 16:33:10 +08:00
 yxcoder

多个 AJAX 请求,分别为 N1,N2,N3,N4,N5

N1 请求完成之后输出 console.log(1) N2 请求完成之后输出 console.log(2) 依此类推

如果 N1,N2,N3,N4,N5 依次执行,但是返回时间不确定,如何使最终输出的只有 5

这里的请求数量可能会很多,五个只是举例。 前者的请求无法取消

3568 次点击
所在节点    程序员
43 条回复
edward1987
2022-08-18 17:08:54 +08:00
// 用闭包变量 res 来承载同一种请求的结果,一旦有新的请求,所有的 req()返回的都指向最新的结果
let res;
function req(){
res = doRequest()
return res
}

async function api(){
const lastRes = await req()
}
del1214
2022-08-18 17:13:23 +08:00
redux saga takelatest
edward1987
2022-08-18 17:16:21 +08:00
@edward1987 有点问题 修正下
// 用闭包变量 res 来承载同一种请求的结果,一旦有新的请求,所有的 req()返回的都指向最新的结果
let res;
async function req(){
res = doRequest();
await res;
return res;
}

async function api(){
const lastRes = await req()
}
dudubaba
2022-08-18 17:17:26 +08:00
封装一个 reduce 就搞定了
dcsuibian
2022-08-18 17:21:51 +08:00
说一下使用场景
怕的就是 xy 问题
qzhai
2022-08-18 17:28:58 +08:00
@shyling
@kop1989smurf

楼主的意思应该是,一个 ajax 的分页 有 5 页,用户依次点击 1 - 5 页的按钮,最终留在某一页,这个时候 ajax 发了 5 此,正常不处理的话,最后一个返回的会 承接当前列表。
qiayue
2022-08-18 17:46:03 +08:00
用一个数组记录每一次的返回结果,再根据前端的状态决定显示哪个结果。
拿分页这个例子来说的话,如果 5 页数据都返回了,那么之后用户点击任何页面,都不需要再发送请求了,直接从已返回结果里拿数据并显示就好了。
wunonglin
2022-08-18 17:49:50 +08:00
rxjs 两三行就可以了。搞那么多乱七八糟的
rrfeng
2022-08-18 17:53:29 +08:00
建议描述下原始需求,console.log 什么的代表不了什么
ITsWHY
2022-08-18 18:07:09 +08:00
@yxcoder id 有很多种形式 比如一个自增的数 或者时间戳
wunonglin
2022-08-18 18:23:35 +08:00
Vegetable
2022-08-18 18:23:38 +08:00
看了你的描述场景,我觉得吧

你直接把展示的价格和展示商品的 ID 做一个映射,显示哪个商品就展示哪个价格,费这么大劲操作请求属于有点把问题搞复杂了
plusor
2022-08-18 18:32:17 +08:00
throttle?
chnwillliu
2022-08-18 18:38:00 +08:00
对,rxjs 下 switchMap 很简单。
dtdths1
2022-08-18 19:19:30 +08:00
最简单的办法就是成功回调时跟最后提交的 id 对比一下,一样再渲染
chnwillliu
2022-08-18 19:24:18 +08:00
就是典型的 switchMap 场景,自动 unsubscribe 上一次产生的流,自动切到最新的流上去。

id$ = new Subject();

price$ = id$.pipe(
switchMap(id => getPriceById(id))
)

// merge + map 很干净,省一个 subject
isLoading$ = merge(
id$.pipe(mapTo(true)),
price$.pipe(mapTo(false))
);

getPriceById 需要返回一个 observable, unsubscribe 时 abort 请求即可。

切商品直接 id$.next(newId), price$ 和 isLoading$ 会自动更新。上一次没完成的请求 switchMap 会自动 unsubscribe ,简直毫无负担。
yxcoder
2022-08-19 10:29:19 +08:00
@chnwillliu 解决办法其实很简单,实在没必要引入 RxJS
@dtdths1 对的,这也是个解决办法,应该会更好一点
markgor
2022-08-19 10:36:40 +08:00
我不是专业前端,
但是这个需求不是应该是节流和防抖的事吗....
另外 ajax 请求是可以 abort 的,
我没理解错的话你意思是 前端快速切换商品,但是由于 ajax 是异步请求,导致最终渲染出来的结果并非最后客户选择的产品结果。
我觉得这种场景上节流,请求异步改同步就能很好解决了,
如果为了体验,可以上骨架,请求前开始骨架渲染,结果返回后取消骨架渲染替换真实结果。
yxcoder
2022-08-19 10:48:26 +08:00
@markgor
1.节流需要获取句柄,暂无法获取
2.受限于框架,无法使用 abort ,问题中已经说过了
3.JS 是单线程,异步改同步会阻塞 JS 进程
4.骨架和文案 “价格查询中...” 有什么本质区别吗?
luvxy
2022-08-19 10:54:01 +08:00
promise.all 就行了 等待所有请求完毕 才会给你返回所有结果

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/873784

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX