本文来介绍一下 JavaScript 中的 Promise。(主要讲一下 Promise 的用途)
Promise 之前的时代——回调时代
假设我们用getUser
来取用户数据,它接收两个回调successCallback
和errorCallback
:
function getUser(successCallback, errorCallback) { $.ajax({ url: '/user', success: function(response) { successCallback(response) }, error: function(xhr) { errorCallback(xhr) } }) }
这段代码看起来还不算复杂。
如果我们获取用户数据之后还要获取分组数组、分组详情等,代码就成了这样:
getUser(function(response) { getGroup(response.id, function(group) { getDetails(group.id, function(details) { console.log(details) }, function() { alert('获取分组详情失败') }) }, function() { alert('获取分组失败') }) }, function() { alert('获取用户信息失败') })
这是三层回调,如果再多一些嵌套,就是「回调地狱」了。
Promise出现了
Promise的思路是,getUser
返回一个对象,我们往这个对象上挂回调:
var promise = getUser() promise.then(successCallback, errorCallback)
当用户信息加载完毕,这两个回调函数之一就会被执行。
将上面两个语句合并成一句就是:
getUser().then(successCallback, errorCallback)
如果你想在用户信息获取结束后做更多事,可以继续.then
getUser().then(success1).then(success2).then(success3)
请求成功后,会依次执行success1、success2和success3。
如果要获取分组信息:
getUser().then(function(response) { getGroup(response.id).then(function(group) { getDetails(group.id).then(function() { }, error3) }, error2) }, error1)
这种 Promise 写法跟前面的回调看起来其实变化不大。
实际上,Promise 并不能消灭回调地狱,但它可以使回调变得「可控」。
对比下面两个写法就知道了:
getGroup(response.id, success2, error2) getGroup(response.id).then(success2, error2)
用 Promise 之前,你无法确定success2是第几个参数;
用 Promise 之后,所有的回调都是
.then(success, error)
这样的形式。