liangbus / blogging

Blog to go
10 stars 0 forks source link

前端页面回退,GET 请求并没有真正发起? #54

Open liangbus opened 3 years ago

liangbus commented 3 years ago

今天排查一个问题,业务场景是这样的:

有两个页面 A 和 B,A 初始化时会请求一个接口获取数据,然后当从 A 页面跳到 B 页面,我在 B 页面做了一些操作,然后更新到服务端去了,我点返回,回到 A 页面,我希望这时候能够获取到在 B 页面所更新的最新数据(回退时主动加载,并非由用户触发)

目前发现的问题是,当我完成在 B 页面的操作后,返回 A 时,执行了请求接口相关的方法,Promise 回调也被执行了,但是通过抓包工具发现,浏览器并没有发起真正的请求。并且获取的数据,也是跳转之前所请求回来的数据

我的目的是,当回到 A 页面的时候,它能够发起请求并获得最新的数据,然而此时通过回退动作返回到 A 页面的,并没有真正发起请求,通过检查发现该接口设置的请求头 Cache-Control 值为 no-cache,这个请求头相信大多数人都比较熟悉,MDN 对其介绍为:

The response may be stored by any cache, even if the response is normally non-cacheable. However, the stored response MUST always go through validation with the origin server first before using it, therefore, you cannot use no-cache in-conjunction with immutable. If you mean to not store the response in any cache, use no-store instead. This directive is not effective in preventing caches from storing your response.

大致意思就是,浏览器下次需要用到缓存数据之前,要去服务端确认该缓存是否可用,假如不想缓存任何数据,请用 no-store 代替

看到这里,大胆猜测就是浏览器默认的缓存行为策略问题,虽然 no-cache 是禁止客户端的缓存了,但针对回退这一行为,浏览器可能有不同的处理,此时我使用代理工具将该 response header 更改为Cache-Control: no-store ,发现回退之后,是通过工作看到浏览器有发起真正的请求的,所以,在这种情况下,就是避免浏览器去使用缓存

除上述方法之外,get 请求添加时间戳,或者改成 post 方式请求,都是可以解决该困境的,但需要注意的是,这样做的收益是否比代价要高,否则我认为是不值得去做的,因为我认为浏览器这个行为,是相对合理的

(在 PC 端 Chrome 浏览器的模拟器总是会发起请求,所以只能在手机端浏览器才能重现上述行为)

网络上,大多数都是讨论在浏览器正常的正向浏览行为,针对回退的讨论相对较少,仅此记录