Javascript XHR/setTimeout/Promise在Chrome中停止滚动之前不会完成

Javascript XHR/setTimeout/Promise在Chrome中停止滚动之前不会完成,javascript,google-chrome,scroll,xmlhttprequest,settimeout,Javascript,Google Chrome,Scroll,Xmlhttprequest,Settimeout,在Chrome中,如果用户正在滚动所有XHR和设置超时将被延迟,直到滚动停止,我需要一个解决方法。中描述了该行为。虽然这个功能有助于移动滚动,但它对无限滚动来说是灾难性的,这正是我要做的 发生这种情况的证据: 所有其他浏览器工作正常,Chrome显示一个空屏幕,直到用户停止滚动 网络面板将所有请求显示为pending,直到滚动结束,然后立即完成 将其放入代码段,运行它,然后立即开始滚动。直到滚动完成后,才会调用setTimeout var p=新承诺(函数(解析){ setTimeout(函

在Chrome中,如果用户正在滚动所有XHR和设置超时将被延迟,直到滚动停止,我需要一个解决方法。中描述了该行为。虽然这个功能有助于移动滚动,但它对无限滚动来说是灾难性的,这正是我要做的

发生这种情况的证据:

  • 所有其他浏览器工作正常,Chrome显示一个空屏幕,直到用户停止滚动

  • 网络面板将所有请求显示为
    pending
    ,直到滚动结束,然后立即完成

  • 将其放入代码段,运行它,然后立即开始滚动。直到滚动完成后,才会调用setTimeout

var p=新承诺(函数(解析){
setTimeout(函数(){
console.log('resolving');
解决();
}, 1000)
});
p、 然后(函数(){
console.log('DONE!!');
})

由于这与发动机有关,我认为不可能找到解决办法。相反,我已经向Chrome团队提交了一份bug报告


根据您的具体情况和所需的浏览器支持,我会尝试-这适用于您正在处理的任务(可以拦截所有流量)或后台的to。

我相信这可能与Chrome的此功能有关:

(被动事件侦听器)

当用户滚动时,Chrome试图避免在移动设备上工作,因此监听touchmove事件有时会延迟处理程序的运行和触发超时

演示:


(查看Handler Jank并在页面上滚动)

我也遇到了同样的问题,有一个无限长的滚动条和一堆图像,最后我能够通过模拟点击文档来“强制”chrome停止取消对更多图像的请求。我知道这听起来很奇怪,但当我进行测试时,只要我滚动,请求就会无限地去抖动,但只要我单击一次,它就会立即执行XHR

我是这样做的…:

export function getPosts() {
  return (dispatch: Dispatch<any>, getState) => {
    const { postFeedState }: IGlobalState = getState();

    dispatch(handlePostsCancellation())

    dispatch({ type: postFeedTypes.GET_POSTS_REQUEST });

    const feedFilterDto = getFeedFilterDto(getState);

    // this is where the clicks are simulated  
    setTimeout(() => {
      for (let i = 0; i < 3; i++) {
        const evt = document.createEvent("Events");
        evt.initEvent("click", true, true);
        window.dispatchEvent(evt);
      }
    }, 50);

    return dispatch(setCancelSource(postFeedTypes.SET_MAIN_FEED_POSTS_CANCEL_SOURCE))
      .then((source) => PostController.getMainFeedPosts(postFeedState.get("postsToSkip"), FeedDisplay.THREE_COLUMNS, feedFilterDto, source))
      .then(posts => dispatch(getPostsSuccess(posts)))
      .catch(error => {
        if (axios.isCancel(error)) return;

        dispatch({ type: postFeedTypes.GET_POSTS_FAILURE });

        dispatch(handleApiError(error, null));
      });
  }
}
导出函数getPosts(){
return(dispatch:dispatch,getState)=>{
常量{postFeedState}:IGlobalState=getState();
分派(handlePostsCancellation())
分派({type:postFeedTypes.GET_POSTS_REQUEST});
const feedFilterDto=getFeedFilterDto(getState);
//这是模拟点击的地方
设置超时(()=>{
for(设i=0;i<3;i++){
const evt=document.createEvent(“事件”);
evt.initEvent(“单击”,真,真);
窗口调度事件(evt);
}
}, 50);
退货派送(setCancelSource(postFeedTypes.SET_MAIN_FEED_POSTS_CANCEL_SOURCE))
.then((source)=>PostController.getMainFeedPosts(postFeedState.get(“postsToSkip”),FeedDisplay.THREE_COLUMNS,feedFilterDto,source))
.then(posts=>dispatch(getPostsSuccess(posts)))
.catch(错误=>{
if(axios.isCancel(error))返回;
分派({type:postFeedTypes.GET_POSTS_FAILURE});
分派(handleAppierRor(错误,null));
});
}
}
我第一次尝试只点击一次,几乎一直有效,然后尝试了2-3次点击,一直有效。老实说,我仍然对超时/点击代码感到有点奇怪,但任何有效的方法都有效!此外,时间会告诉我们这是否会继续工作,但现在这是我找到的最好的解决方案和最简单的解决方案


注:我使用redux和axios,并为我的端点(后控制器)提供了自己的自定义类,但它所做的只是一个axios(XHR)请求。

使用
requestAnimationFrame()
而不是
setTimeout()
会有帮助吗?这篇博文非常清楚地表明,Chrome正在优先处理动画和GPU相关任务,这样用户体验(他们正在做的事情)就不会受到影响。是的,确实如此!然而,这对XHRs没有帮助,这对无限卷轴来说很重要。我有一个确切的问题,希望得到一个答案。开始为你悬赏。@SebastianOlsen我似乎无法复制这个问题,即使有XHR。你能做一个MCVE吗?@sakabako,你解决了这个问题吗?如果是,怎么解决?我正在处理无限滚动的问题,这让我发疯。除了Chrome,其他浏览器都可以正常工作。那么SoundCloud和其他网站怎么会没有这个问题呢?确实有一种方法可以防止它。实际上,我在复制这张照片时遇到了困难。我刚刚用上面的超时代码快速创建了一个页面,在滚动时我得到了控制台的输出。这就是我遇到的问题。我检查了开发工具,它显示了一些来自第三方库的不需要的触摸侦听器。禁用此库解决了我的滚动问题。我在“mousewheel”事件中添加了一个空事件侦听器,并为我修复了它(类似于此处的建议)