Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

day-10-异步代码同步响应同时不干扰dom操作 #10

Open
H246802 opened this issue Nov 30, 2018 · 4 comments
Open

day-10-异步代码同步响应同时不干扰dom操作 #10

H246802 opened this issue Nov 30, 2018 · 4 comments

Comments

@H246802
Copy link
Owner

H246802 commented Nov 30, 2018

某个应用模块由文本框input,以及按钮A,按钮B组成。点击按钮A,会向地址urlA发出一个ajax请求,并将返回的字符串填充到input中(覆盖掉input中原有的数据),点击按钮B,会向地址urlB发出一个ajax请求,并将返回的字符串填充到input中(覆盖input中原有数据)。
当用户依次点击按钮A、B时,预期的效果是input依次被urlA、urlB返回的数据填充,但是由于urlA的请求返回比较慢,导致urlB返回的数据被urlA的数据覆盖了,与用户预期的顺序不一致。

问:应该如何设计代码,解决这个问题

@H246802
Copy link
Owner Author

H246802 commented Nov 30, 2018

工作中其实也常常有这样的需求返回之前不让再次发送请求,一般是在点击后,请求前使用一个全局的遮罩完成。

  • 在ajax之前使用 loading.mask()
  • 成功后loading.unmask()
    image

但这样和题目要求不符合,用户点击A按钮后就在一段时间内无法点击B按钮,所以答案算是错误的。

@H246802
Copy link
Owner Author

H246802 commented Nov 30, 2018

因为没有服务器,所以先使用定时器进行不确定时间模拟

因为代码是需要点击后依次返回,所以代码应该将每次执行函数都放置到一个数组,依次执行。

@H246802
Copy link
Owner Author

H246802 commented Nov 30, 2018

第二次尝试,通过promise.then的链式结构,我们可以实现一次一次的异步执行

$('.btn1').click(function(){
  next('按钮1')
  
})
$('.btn2').click(function(){
   next('按钮2')
  
})
$('.btn3').click(function(){
   next('按钮3')
  
})

let num = 0
let next = (function(){
  // 使用闭包是为了让代码都沿用同一个promise
  let promise = new Promise(function(resolve){resolve()})
  // or
  // let promise = Promise.resolve()
  return function(url){
    promise = promise.then(()=>{
      return new Promise((resolve)=>{
        setTimeout(()=>{
          num ++
          console.log(`第${num}次打印的是${url}`)
          resolve()
        },3000 * Math.random())
      })
    })
  }
})() 

jsbin代码,依次发起网络请求

@H246802
Copy link
Owner Author

H246802 commented Nov 30, 2018

其他方法

buttonA.onclick = function() {
    get('/a', function(resTxt) {
        console.log(resTxt)
        input.value = resTxt
    })
}

buttonB.onclick = function() {
    get('/b', function(resTxt) {
        console.log(resTxt)
        input.value = resTxt
    })
}

function get(url, callback) {

    if (!Array.isArray(get.xhrQueue)) {
        get.xhrQueue = []
    }
    var xhrQueue = get.xhrQueue
    var xhr = new XMLHttpRequest()
    xhrQueue.push(xhr)
    xhr.opts = {}
    xhr.onloadend = function() {
        this.opts.finished = true
        checkQueue()
    }

    xhr.opts.finished = false
    xhr.opts.callback = callback
    xhr.timeout = 1000 * 8
    xhr.open('get', url, true)
    xhr.send()

    function checkQueue() {
        var xhr = xhrQueue[0]
        while (xhr && xhr.opts.finished) {
            if (xhr.status == 200 || xhr.status == 304) {
                xhr.opts.callback(xhr.responseText)
            }
            xhrQueue.shift()
            xhr = xhrQueue[0]
        }

    }
}

@H246802 H246802 changed the title day-10-异步代码同步显示 day-10-异步代码同步响应同时不干扰dom操作 Nov 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant