问题的发现【原创内容,转载请注明出处】
【关注微信公众号:wwwtangshuangnet】【作者:唐霜】著作权归作者所有,禁止商业用途转载。来自同源的多个异步操作可能引起异步冲突问【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net题,特别是在网络请求时。同源操作产生了两【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】个ajax请求,它们的请求结果将用于渲染著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。同一个区域,然而由于网络问题,先发出的请【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net求后返回,导致最终得到的界面是错误的。
【未经授权禁止转载】【原创内容,转载请注明出处】【本文受版权保护】【原创不易,请尊重版权】解决这个问题的最好办法,是利用原生XHR著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。的abort方法,在后一次操作时,将前一【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】次操作引起的ajax请求给cancel掉著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net。
本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【未经授权禁止转载】【原创内容,转载请注明出处】但是在现实条件下,异步操作并非都有can【未经授权禁止转载】【版权所有,侵权必究】cel操作。js原生的Promise没有【作者:唐霜】原创内容,盗版必究。,原生的fetch基于Promise也没原创内容,盗版必究。【原创内容,转载请注明出处】有。基于Promise的很多工具都没有c【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netancel操作。这种情况下怎么解决这个问本文作者:唐霜,转载请注明出处。【未经授权禁止转载】题呢?
著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。原创内容,盗版必究。其实方法是有的,就是直接丢弃Promis转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。e的推送,不执行它的resolve回调即【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。可。这样,虽然异步操作已经执行了,但不会【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】对现有的环境造成任何副作用。(虽然这样看原创内容,盗版必究。转载请注明出处:www.tangshuang.net上去浪费了异步操作这个资源。)
【作者:唐霜】【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】未经授权,禁止复制转载。问题的思考【作者:唐霜】
著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net原创内容,盗版必究。如何来判断是否要丢掉它的回调?我们可以创【未经授权禁止转载】【未经授权禁止转载】建一个队列,每次产生一个异步操作时,就将【作者:唐霜】【版权所有】唐霜 www.tangshuang.net它加入到队列中,当队列中存在操作对象时,著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net每次只取最后一个,等待它推送结果,执行它【转载请注明来源】【关注微信公众号:wwwtangshuangnet】的回调,排在它前面的操作全部丢弃掉。
转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】基于这样的想法,我写了一个工具defer【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.neter-queue。它为异步操作创建队列,【本文受版权保护】【版权所有】唐霜 www.tangshuang.net并根据不同的场景实现不同的队列操作形式。【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】你可以通过这里阅读它的源码和文档未经授权,禁止复制转载。。它提供了4种可供选择的场景:本文作者:唐霜,转载请注明出处。
未经授权,禁止复制转载。【未经授权禁止转载】本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net并联著作权归作者所有,禁止商业用途转载。
【本文受版权保护】转载请注明出处:www.tangshuang.net【作者:唐霜】转载请注明出处:www.tangshuang.net【作者:唐霜】异步操作进入队列的时候立即开始执行,它们本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。的回调将按照它们进入队列的顺序执行。
原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。【原创内容,转载请注明出处】 【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】这个图中有这些元素:【作者:唐霜】
【原创不易,请尊重版权】【本文受版权保护】【转载请注明来源】本文作者:唐霜,转载请注明出处。- 时间轴【本文受版权保护】 原创内容,盗版必究。【本文受版权保护】未经授权,禁止复制转载。【未经授权禁止转载】
- 圆圈:一个异步操作被push进队列原创内容,盗版必究。 【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net
- 向下箭头:队列中开始执行某个异步操作本文作者:唐霜,转载请注明出处。 【原创不易,请尊重版权】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。
- 虚线:执行顺序(执行流)【原创内容,转载请注明出处】 【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【本文首发于唐霜的博客】【版权所有,侵权必究】
- 方框:每个异步操作的回调【作者:唐霜】 【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】
- 竖线:队列周期(从开始到停止的过程)分割本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。线 【原创内容,转载请注明出处】【原创内容,转载请注明出处】【版权所有,侵权必究】
上图表现的是,1-4这4个异步操作在不同【本文受版权保护】【本文首发于唐霜的博客】的事件点被加入到队列中。它们在一个周期内原创内容,盗版必究。【原创内容,转载请注明出处】,也就是从1开始执行,到队列中所有的异步著作权归作者所有,禁止商业用途转载。【转载请注明来源】操作执行完毕,进入停滞状态。1-4这些操【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】作,一进入队列就开始执行。它们执行完之后本文作者:唐霜,转载请注明出处。原创内容,盗版必究。,就会告知队列执行完毕状态,回调就会执行未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。。但是由于回调一定是按照异步操作进入队列【转载请注明来源】转载请注明出处:www.tangshuang.net的顺序执行的,因此,即使4已经完成了,但未经授权,禁止复制转载。【未经授权禁止转载】它的回调也必须等到3结束后才会执行。
转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。【本文受版权保护】在deferer-queue中,所有的回转载请注明出处:www.tangshuang.net【作者:唐霜】调一定遵循先进队列先执行,后进队列后执行著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net的顺序规则。
原创内容,盗版必究。【原创内容,转载请注明出处】【未经授权禁止转载】本文作者:唐霜,转载请注明出处。串联【原创内容,转载请注明出处】
转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】【未经授权禁止转载】转载请注明出处:www.tangshuang.net异步操作进入队列后并不立即执行,它从队列【转载请注明来源】【本文受版权保护】中取出第一个,执行,等待这个异步操作完成本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】(成功或失败都算完成)并执行它的回调,然【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。后再取出下一个,继续执行。
转载请注明出处:www.tangshuang.net原创内容,盗版必究。【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net 【未经授权禁止转载】【本文受版权保护】【本文首发于唐霜的博客】上图表现的是,1-4这4个异步操作,进入原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net队列后,按照顺序依次执行。但是,在一个周【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】期内,只有1是立即执行的,其他操作必须等【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】到上一个操作结束(promise res【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netolved或rejected)之后,才会【作者:唐霜】未经授权,禁止复制转载。开始执行。
转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】尾调【原创内容,转载请注明出处】
未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】【本文受版权保护】【转载请注明来源】【本文受版权保护】异步操作进入队列后并不立即执行,它从队列转载请注明出处:www.tangshuang.net【转载请注明来源】中取出最后一个,执行,并把前面所有的操作本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net丢弃,这个操作执行完后直接进入回调,队列本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。结束。
【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。
这张图表现的是,1-4这个4个异步操作被原创内容,盗版必究。转载请注明出处:www.tangshuang.net按顺序加入到队列中,但是,在一个周期内,【转载请注明来源】本文作者:唐霜,转载请注明出处。只有4(最后一个)被执行。1-3全部被丢未经授权,禁止复制转载。【本文受版权保护】掉了。你可能会问,假如4进入队列的时候,【本文首发于唐霜的博客】未经授权,禁止复制转载。1已经在执行了怎么办?答案是,1会被丢掉【转载请注明来源】【本文受版权保护】,只要在一个周期内,只会有一个执行的回调转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。会被执行。也就是说,假如4开始执行之后,著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。突然5插入进来了,那么4会被直接丢掉,这本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】一个周期以最后一个回调函数被执行而结束。
【原创内容,转载请注明出处】【转载请注明来源】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】连续【关注微信公众号:wwwtangshuangnet】
本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。异步操作进入队列后并不立即执行,它从队列【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】中取出第一个,执行,等待这个异步操作完成【原创不易,请尊重版权】【作者:唐霜】(成功或失败都算完成)并执行它的回调,之未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。后取出最新的一个执行,执行完之后再看队列【转载请注明来源】【转载请注明来源】中是否有新的,如果有新的,再取出最新的一【未经授权禁止转载】【版权所有,侵权必究】个,继续执行,如此往复下去。
【本文首发于唐霜的博客】【原创内容,转载请注明出处】【本文受版权保护】 本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【作者:唐霜】【本文受版权保护】这幅图表面的是一种连续不断的执行队列的模【本文首发于唐霜的博客】【本文首发于唐霜的博客】式,当1-4被push进队列之后,1被执【作者:唐霜】转载请注明出处:www.tangshuang.net行,2-4被丢掉。当1完成之后,检查队列【原创不易,请尊重版权】【作者:唐霜】是否加入了新的异步操作,如果检查到5-6【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。,那么取6进行执行,把5丢掉。进入后续过【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net程后,感觉上和尾调非常像,但是,尾调是在本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】一个周期内,只会执行最后一个回调,而连续著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net不是,它会不断的检查队列是否已经被执行完本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。,如果没有,那么就会执行一个类似尾调的过【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】程,这个过程结束,又会再做一次。队列开始【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】的时候,取第一个异步操作执行,当第一个操本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。作结束后,后面之后去取最后一个执行。这些本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】执行之间是串联关系,只有正在执行的异步操【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。作已经完成的情况下,新的操作才会被执行。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】这是一种比较奇葩的场景,但是它可以解决一原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】些需要连续不断做某些事情的应用。
著作权归作者所有,禁止商业用途转载。【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net注意:当一个周期结束后,队列处于停滞状态本文作者:唐霜,转载请注明出处。【本文受版权保护】,但是,一旦有新的defer被push进【转载请注明来源】【原创不易,请尊重版权】队列,它又会开始一个新的周期。
【版权所有,侵权必究】原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net问题的解决原创内容,盗版必究。
【作者:唐霜】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net基于上述的思考,我最终发布了defere【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netr-queue,你可以通过npm安装这个【版权所有,侵权必究】原创内容,盗版必究。包,在自己的项目中使用它。它的操作模式超【转载请注明来源】【本文首发于唐霜的博客】级简单,首先实例化一个queue对象,然原创内容,盗版必究。【版权所有,侵权必究】后往这个queue push异步操作,异未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。步操作被装在一个函数中被push进队列,【版权所有,侵权必究】原创内容,盗版必究。它的回调函数一定是按照push的顺序执行原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net。
【版权所有,侵权必究】【作者:唐霜】【转载请注明来源】【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】import DefererQueue from 'deferer-queue'
const queue = new DefererQueue()
const defer1 = () => new Promise((resolve, reject) => { ... })
const defer2 = () => axios.get(...)
const defer3 = async () => ...
queue.push(defer1).then(() => { console.log(1) })
queue.push(defer2).then(() => { console.log(2) })
queue.push(defer3).then(() => { console.log(3) })
无论defer1-3中的谁,执行后谁先返【关注微信公众号:wwwtangshuangnet】【本文受版权保护】回结果,控制台输出的结果永远是1 2 3未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net(defer都成功的前提下)。
【转载请注明来源】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net要使用上述的四种模式,只需要在实例化的时【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。候,传入一个options对象,将mod【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.nete设置为parallel/serial/著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】switch/shift中的一个即可:
【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。const queue = new DefererQueue({
mode: 'switch',
})
其他的用法一样。这样,你的队列就会按照“【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net尾调”的模式运行。
本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net【版权所有,侵权必究】未经授权,禁止复制转载。关于具体的API使用细则,你可以阅读它的文档【关注微信公众号:wwwtangshuangnet】。其中,利用axios的cancel能力【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】那个地方非常有借鉴意义。
转载请注明出处:www.tangshuang.net【本文受版权保护】本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net



