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

利用 jQuery.when 简化代码 #56

Open
YIXUNFE opened this issue Feb 14, 2016 · 0 comments
Open

利用 jQuery.when 简化代码 #56

YIXUNFE opened this issue Feb 14, 2016 · 0 comments

Comments

@YIXUNFE
Copy link
Owner

YIXUNFE commented Feb 14, 2016

利用 jQuery.when 简化代码

最近有一些项目,是从已有的功能上新增一些数据,比如个人账户中新增一些数据。后端并没有在原有接口上提供所需数据,而是希望我们调用另一个接口,这个接口仅仅提供新增的数据。

由于新接口和旧接口在数据上并没有依赖关系,所以我们可以等两个接口都请求完成后将数据填充到 DOM 结构中。在这个问题的解决过程中就出现了一些不太简洁的代码,比如:

var len = 2, data = {}
  cb = function () {...}

//一个请求
$.ajax({
  url: url1,
  ...
}).then(function (d) {
  len--
  $.extend(data, d)
  if (len === 0) {
    cb(data)
  }
})

//又一个请求
$.ajax({
  url: url2,
  ...
}).then(function (d) {
  len--
  $.extend(data, d)
  if (len === 0) {
    cb(data)
  }
})

这种解决方案虽然能处理当前项目中的实际问题,但是当这类无序的异步请求是 N 个的时候,这种方法就有点捉襟见肘了。而利用 jQuery.when 方法,即能很好的解决这些问题,而且能够使代码简洁优雅易于维护。

$.when($.ajax({
  url: url1,
  ...
}), $.ajax({
  url: url2,
  ...
})).done(function (data1, data2) {...}).fail(function () {...})

简洁明了了许多吧:smile:


## jQuery.when 的参数

上面提到将多个异步请求作为参数传入 jQuery.when 方法中,这个描述并不正确,因为 jQuery.when 接受的是延迟对象(jQuery.Deferred),巧在 jQuery.ajax 方法返回的 jqXHR 对象(浏览器原生 XHR 对象的超集)就是一个延迟对象(jQuery 1.5+),所以看上去我们是将 jqXHR 对象作为了参数,这确实让人产生了一定的误解。

在处理普通的延迟问题的时候,我们就需要在异步方法中明确地返回延迟对象。

var dfd1 = new $.Deferred(),
  dfd2 = new $.Deferred()

function wait1 (dfd) {
  setTimeout(function () {
    dfd.resolve('wait1 done')
  }, 1000)
  return dfd.promise()
}

function wait2 (dfd) {
  setTimeout(function () {
    dfd.resolve('wait2 done')
  }, 2000)
  return dfd.promise()
}

$.when(wait1(dfd1), wait2(dfd2)).done(function (data1, data2) {
  console.log(data1)  // 'wait1 done'
  console.log(data2)  // 'wait2 done'
})

## done、fail、then 方法

jQuery.when 方法返回的是一个 Promise 对象(延迟对象的一个子集),可以调用它的 donefailthen 方法执行回调函数。这里列一下这些方法中回调函数的执行条件。

  • done 所有延迟对象都执行成功(resolved)时执行;
  • fail 有一个延迟对象失败(rejected)时即执行,即使还有未完成的延迟对象;
  • then 所有延迟对象完成后执行,可以传入两个回调函数作为参数,第一个参数在全部延迟对象成功时执行,第二个参数在有一个或多个延迟对象失败时执行。

另外需要注意的是,当 jQUery.when 方法被传入了一个以上的参数时,回调函数中的参数可能是一个数组。因为在传递给一个延迟对象的解决(resolved)事件为多个值的情况下,相应的参数将是这些值组成的数组。

var dfd1 = new $.Deferred(),
  dfd2 = new $.Deferred()

function wait1 (dfd) {
  setTimeout(function () {
    dfd.resolve('wait1', 'done')
  }, 1000)
  return dfd.promise()
}

function wait2 (dfd) {
  setTimeout(function () {
    dfd.resolve('wait2', 'done')
  }, 2000)
  return dfd.promise()
}

$.when(wait1(dfd1), wait2(dfd2)).done(function (data1, data2) {
  console.log(data1)  // ['wait1', 'done']
  console.log(data2)  // ['wait2', 'done']
})

## 参考资料

jQuery.ajax API 传送门
jQuery.when API 传送门


## Thanks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant