Callback Hell和ECMAScript6 Promise
Promise 是 “14nodejs(7天)” 第五天的课程,但是 Promise 并不属于 Node.js 的内容,而是 ECMScript6 新增的 api
回调地域(Callback Hell)
回调地域 既一个异步请求需要另一个异步请求结果
$.ajax({url, success: function () { ... }})
$.ajax({url, success: function () { ... }})
$.ajax({url, success: function () { ... }})
$.ajax({url, success: function () { ... }})
由于 Javascript 是单线程的,所以这里执行顺序是 ajax1 -> ajax2 -> ajax3 -> ajax4
但是又由于这四个是异步操作,所以这种多线程操作会导致执行顺序不固定
为了保障异步函数的执行顺序,可以通过异步套异步的方式解决
$.ajax({url, success: function () {
$.ajax({url, success: function () {
$.ajax({url, success: function () {
$.ajax({url, success: function () { ... }})
}})
}})
}})
以上这种写法就是所谓的回调地域,非常的不利于维护
为了解决这一情况,ECMAScript6 新增了 Promise API
Promise(承诺)
可以理解 Promise 为一个容器,它包含三个状态,分别为 Pending(正在执行) 、Resolved(已解决) 、Rejected(未解决)
Promise 本身并不是异步的,但其包裹的内容函数为异步函数
// 通过 new Promise 创建 Promise 容器
// 实例化 Promise
var p1 = new Promise (function (resolve, reject) { // Promise 容器(它本身不是异步方法)
$.ajax({ // $.ajax 异步方法
url,
success: function () {
resolve(data) // 改变容器状态为成功
},
error: function () {
reject(err) // 改变容器状态为失败
}
})
})
容器接收两个形参:
resolve 改变容器状态为成功reject 改变容器状态为失败通过 .then() 决定实例成功后的指定操作
p1.then(function (data) {
console.log(data) // 接收 p1 实例成功状态 resolve 抛出的数据 data
return p2 // 返回第二个 Promise 容器
}, function (err) {
console.log(err) // 接收 p1 实例失败状态 reject 抛出的数据 data
})
.then 包含两个函数参数:
第一个函数的参数接收 Promise 容器中的 resolve 抛出的成功内容第二个函数的参数接收 Promise 容器中的 reject 抛出的失败信息在 .then 的第一个函数中可以返回数据,此数据可以提供给后续 .then 接收使用
如果没有 return 返回值,则后续接收到 undefined如果 return 返回一个 Promise 对象时,后续 .then 第一个函数接收该 Promise 对象的 resolve 状态,第二个函数接收该 Promise 对象的 reject 状态到此,通过以上的介绍可以 优化回调地域(Callback Hell)
// 通过 new Promise 创建 Promise 容器
// 实例化 Promise
var p1 = new Promise (function (resolve, reject) { // Promise 容器(它本身不是异步方法)
$.ajax({ // $.ajax 异步方法
url,
success: function () {
resolve(data) // 改变容器状态为成功
},
error: function () {
reject(err) // 改变容器状态为失败
}
})
})
var p2 = new Promise (function (resolve, reject) { ... })
var p3 = new Promise (function (resolve, reject) { ... })
var p4 = new Promise (function (resolve, reject) { ... })
// 操作实例
p1
.then(function (data) {
console.log(data) // 打印 p1 的 data 内容
return p2 // 向下传递实例 p2
}, function (err) {
console.log(err) // 打印 p1 的 err 信息
})
.then(function (data) {
console.log(data) // 打印 p2 的 data 内容
return p3 // 向下传递实例 p3
}, function (err) {
console.log(err) // 打印 p2 的 err 信息
})
.then(function (data) {
console.log(data) // 打印 p3 的 data 内容
return p4 // 向下传递实例 p4
}, function (err) {
console.log(err) // 打印 p3 的 err 信息
})
.then(function (data) {
console.log(data) // 打印 p4 的 data 内容
}, function (err) {
console.log(err) // 打印 p4 的 err 信息
})通过判断是否有 then 方法判断其是否是 Promise 对象
var p1 = new Promise (function (resolve, reject) { ... }
function p2 () { ... }
// 替换下段代码中的 fn 即可查看 P1、P2 是否是 Promise 对象
if (!!fn && typeof fn.then === 'function') {
console.log('是Promise')
} else {
console.log('不是Promise')
}文章已同步我的个人博客:《Callback Hell和ECMAScript6 Promise》
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!