小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
jquery, axios, fetch 的区别
jquery ajax: 是对原生 XHR 的封装,除此以外还增添了对 JSONP 的支持。但为了这个功能需要引入一个庞大的 jq 库,并且,对异步的支持不是太友好
axios ajax: 一个基于 Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生 XHR 的封装,只不过它是 Promise 的实现版本,符合最新的ES规范,也是现在主流使用的 ajax 库
fetch: 使用了ES6中的 Promisse 对象。但是,fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
总结起来:jquery ajax 建议放弃。如果正经的项目开发,建议上 axios。要是不正经的,或者是小 demo,直接用原生的 fetch 梭哈
场景假设
我们需要去轮询一个接口,同时对返回的数据做一个处理,我们可以借助 setInterval
大致的代码会如下:
let timeId = setInterval(() => {
fetch(url, config)
}, time)
这种方式存在一个问题,fetch 中的操作,是异步的,假定执行完成后得到结果需要 2s,但轮询间隔为 1s,表现效果就是以为会有间隔时间,但实际是连着一直在做,由于消化不了,浏览器最后会被 setInterval 产生的任务撑到裂开
聊到 setInterval 就不得不提宏任务和微任务,宏任务指浏览器当前执行的主线任务,微任务就是支线任务,这是两个有序的队列。当在当前的时间节点,主线任务都搞定了,就会去拿一个支线任务来当主线来做,一直循环直到两条线的任务都搞定。
而 setInterval,负责定时产生任务,然后往支线队列扔,这只管产生,不管执行。至于什么时候做,则需要浏览器的线程来调度。调度的依据就是上一段所说
总结起来,setInterval,传入的时间参数,并不是指多次任务执行期间的间隔,而是指下一次任务产生的间隔时间,什么时候执行这次任务还需要看系统当前的运行环境
改进
为 fetch 包裹一个名为 call 的函数,在 fetch 执行的结果里,使用 setTimeout 去执行下一次 call,整个调用链有点类似于链表,只有等当前函数执行完成之后,才会去执行下一次
{
call();
function call(time = 1200) {
fetch("https://cn.bing.com/hp/api/model", {
"headers": {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"sec-ch-ua": "\"Chromium\";v=\"94\", \"Google Chrome\";v=\"94\", \";Not A Brand\";v=\"99\"",
},
"referrer": "https://cn.bing.com/",
"referrerPolicy": "strict-origin-when-cross-origin",
}).then(rep => rep.json()).then((data) => {
setTimeout(() => call(time), time)
});
}
}
如果要根据条件来终止呢?
进一步的思考,以掘金的抽奖接口为例,我们手里有 1000矿,但实际抽奖的次数,不一定是 5次,终止的条件就变成了:一直抽奖,直到抽奖接口返回抽奖失败
思路为:我们引入一个标记 flag,定义 flag=ture 一直抽,flag=false 则结束抽奖
- 在
call中的第一行先判断flag,为false则终止,并执行统计函数,输出大伙的战果- 如果是
true,则调用fetch
- 在
fetch回调里使用setTimeout来定义下一次调用 - 根据此次的结果来判断是否需要调整
flag为false
大致的代码如下:
function choujiang() {
let nextLotteryFlag = true;
asyncFetch(() => {})
function asyncFetch(callback, time = 1200) {
if (!nextLotteryFlag) {
callback();
return;
};
setTimeout(() => {
fetch(`https://api.juejin.cn/growth_api/v1/lottery/draw?${userInfo}`, httpConfig)
.then(resp => resp.json()).then(data => {
if (data.err_msg == 'success') {
console.log(name);
} else {
nextLotteryFlag = false;
}
asyncFetch(callback, time);
})
}, time)
}
return false;
}
原创不易,期待大家的鼓励❤~