Ajax 异步与同步(jQuery 在函数中修改全局变量)
还是最近在做的那个漫画网站,商定详情页面以无限下拉方式来体现,取消古板的下一章,下一页这样的高频点击按钮。这种方式的请求就得用Ajax来发送。首先绑定一个下拉滚动条到达某一位置的事件函数,然后在其中编写Ajax的逻辑。这里呢首先就遇到一个问题:由谁来决定请求的内容?这个问题在我当前的具体业务中前端后端都可以实现,无非就是谁来做,谁的逻辑就会复杂一点,考虑到前端朋友天天带刀上班,于是主动把这个任务交予后端来做……手动狗头保命
具体方式就是在后端响应的数据中,除了发送当前请求的图片URL之外,还要包含前端下一次请求的具体内容(哪本漫画,哪一章节,哪一页),这样前端就只需要把响应数据存下来,等着下一次发送请求就OK了。
如何存储响应数据呢?这里可以使用jQuery调用cookie来保存数据,但是小玉觉得呢,cookie这个东西,貌似不是每种客户端都有的,于是想了一个偏方……创建全局变量来存储这三个数据。
由于Ajax是在函数内部执行,无法直接对全局变量进行修改,需要用到一个方法:window.变量名 = 数据; 这样就可以修改函数体外部的全局变量。
小玉一开始设计的是,当滚动条触底之后,向后端发起三次请求,每一次请求的参数,都由上一次请求的响应来决定。设计是很美好的,直到运行程序……
这里小玉完全忽略了Ajax最根本的属性:异步性,导致了什么样的结果呢:
上图里的两条控制台打印语句,想要的是一对一的交替打印,结果却是:
这样的结果意味着,同样的请求,发了两次(实际上看网页页面效果是同样的请求发了三次)(别问,我也不明白)
这就是Ajax异步的效果体现,那个for语句不会等到Ajax执行完毕再开始下一轮循环,它会直接将三次循环全部执行,就像是后端的线程池技术。
要解决这个问题,百度给出的方案是:将Ajax从异步变为同步,这个方案一开始小玉是不同意的,Ajax本来就是一个前端的异步技术,这下要把它设置成同步来运行,这TM不是疯了吗???奈何自己也没有找到更好的办法来解决这个问题,于是,疯了就疯了吧……最终还是给Ajax添加了一行属性:
这条属性就是让Ajax采用同步运行的方式。
虽然输出变成了想要的样子,但是浏览器也给出了一条赤裸裸的提示:不建议使用同步的方式!
后来小玉仔细想了想,感觉还有一种办法貌似能够在不设置同步的情况下实现这一需求:那就是去掉for循环,直接把Ajax嵌套三层
我擦,你别说蠢,这种办法还真的行
于是,小玉决定采用这种看起来很蠢的办法,至少不会弹警告
最后,素质三连,赠送代码
<div id="container" style="text-align: center"></div>
<div class="scrollerFooter1">
没有内容了
</div>
<script>
var bookID = {{ book_id }};
var chapterID = {{ chapter_id }};
var page = 1;
function infinityScroll(footerNode, callback) {
var observer = new IntersectionObserver(function (changes) {
if (changes[0].intersectionRatio <= 0) return;
callback();
});
observer.observe(document.querySelector(footerNode));
}
infinityScroll('.scrollerFooter1', function pictuer(i=3) {
$.ajax({
url: '/index/content/' + bookID + '/' + chapterID + '/' + page,
type: 'GET',
dataType: 'json',
success: function (res) {
html_1 = res.url;
if (html_1) {
html_1 = '<div class="img-area"><img class="my-photo" alt="loading" code-snippet_outer"> html_1 += '"/></div>';
$('#container').append(html_1);
window.bookID = res.book_id;
window.chapterID = res.chapter_id;
window.page = res.page_id;
console.log('====', bookID, chapterID, page);
i -= 1;
if (i) {
pictuer(i)
}
} else {
$('#container').append('<h1>没有了</h1>');
return null
}
}
});
});
</script>
</body>