Open EmberYu opened 5 years ago
昨天晚上小伙伴发了我一个文章,标题很吓人,叫如果你想靠前端技术还房贷,你不能连这个都不会,刚好戳中了我这个潜在富一代买不起房的痛点。吓得我赶紧点进来看了一下,吭哧吭哧大概花了三个小时才搞出来,做完又开始发愁了,房贷可能交得起了,这首付是国家发还是自己领呢。 好了不扯了回到正题
知乎地址 https://zhuanlan.zhihu.com/p/25259283 某个应用模块由文本框 input,以及按钮 A,按钮 B 组成。点击按钮 A,会向地址 urlA 发出一个 ajax 请求,并将返回的字符串填充到 input 中(覆盖 input 中原有的数据),点击按钮 B,会向地址 urlB 发出一个 ajax 请求,并将返回的字符串填充到 input 中(覆盖 input 中原有的数据)。 当用户依次点击按钮 A、B 的时候,预期的效果是 input 依次被 urlA、urlB 返回的数据填充,但是由于到 urlA 的请求返回比较慢,导致 urlB 返回的数据被 urlA 返回的数据覆盖了,与用户预期的顺序不一致。 请问如何设计代码,解决这个问题?
建议可以自己先尝试一下看能不能写出来 想看答案的可以直接戳这里
首先这道题肯定是一个将异步队列按同步的顺序返回的问题。先返回的如果不是队列的第一个任务,那么结果将会被保留下来,一直等到队列第一个任务返回时出栈,轮到自己到第一个队列时才执行。
html很简单,第一个按钮点击后等3s返回结果。第二个按钮点击1s后返回结果。为了让效果更明显,我们将返回的结果依次输出在container这个class 中
container
class
我们首先模拟两个请求 正常情况下我们的请求一般都是这样的,返回一个promise。接下来看一下我们对两个按钮进行方法绑定 这样就完成了按钮绑定,将返回的结果输出到页面中这个方法,但是由于异步返回时间的不同,他们的顺序并不是按照点击的顺序来的,这里就到了问题的难点了。如何让异步的请求按照同步的结果返回?问题大概可以归纳为几个步骤
createSyncTask
taskQueue
push
Promise
pending
resolve
triggerTaskFinish
完整js代码如下
如果有什么不足的地方欢迎评论指正。毕竟我也只是个小菜鸡
昨天晚上小伙伴发了我一个文章,标题很吓人,叫如果你想靠前端技术还房贷,你不能连这个都不会,刚好戳中了我这个潜在富一代买不起房的痛点。吓得我赶紧点进来看了一下,吭哧吭哧大概花了三个小时才搞出来,做完又开始发愁了,房贷可能交得起了,这首付是国家发还是自己领呢。
好了不扯了回到正题
问题
建议可以自己先尝试一下看能不能写出来
想看答案的可以直接戳这里
问题分析
首先这道题肯定是一个将异步队列按同步的顺序返回的问题。先返回的如果不是队列的第一个任务,那么结果将会被保留下来,一直等到队列第一个任务返回时出栈,轮到自己到第一个队列时才执行。
首先我们先写html页面
html很简单,第一个按钮点击后等3s返回结果。第二个按钮点击1s后返回结果。为了让效果更明显,我们将返回的结果依次输出在
container
这个class
中然后我们写js代码
我们首先模拟两个请求
正常情况下我们的请求一般都是这样的,返回一个promise。接下来看一下我们对两个按钮进行方法绑定
这样就完成了按钮绑定,将返回的结果输出到页面中这个方法,但是由于异步返回时间的不同,他们的顺序并不是按照点击的顺序来的,这里就到了问题的难点了。如何让异步的请求按照同步的结果返回?问题大概可以归纳为几个步骤
代码如下
这里可以看到,我们用了一个
createSyncTask
方法,用高阶函数的方法,将异步的队列传入,并返回一个组装后的高阶函数。当调用这个高阶函数时,就向taskQueue
里push
进一个任务。同时让它的Promise
一直处于pending
状态,当执行完毕后,才改为resolve
。同时触发队列中已经有任务完成的方法triggerTaskFinish
而
triggerTaskFinish
方法就很简单了。判断当前队列第一个是否已经resolve
,如果resolve
。那么就将它的Promise
方法状态设置为resolve
,同时将返回值传入。那么接下来,我们只需要将原来的异步请求包装一下即可实现需求
好了,那么我们就可以实现任务是根据我们点击顺序来实现的效果了。而且这种写法,如果不需要同步了或者增加新的按钮,后面改起来也比较方便。
完整js代码如下
如果有什么不足的地方欢迎评论指正。毕竟我也只是个小菜鸡