概述
场景:
js中多个异步调用(接口,读取文件)时没有顺序,若业务现在要求有顺序的调用,就只能嵌套回调,如果嵌套回调3个以下代码量还不是很多,还可以凑乎,超过3个后重复代码多,可维护性差,代码丑陋ugly,就造成了callback hell,这也就是:回调地狱。如下图所示。
解决方案
对此,Es6出了promise解决此问题。而且,jquery也支持promise功能,node中的mongoose也支持promise功能。
promise容器概念: pending正在进行后有2种状态,要么成功变成resolved,要么失败变成rejected,如图所示:
new Promise(function(resolve,reject){异步操作})
,如下图所示
-
在 promise 对象.then(fun1,fun2)方法中,
resolve(data)
执行fun1方法,reject(err)
执行的是fun2方法 -
如果在 then 的 fun1 方法中 return 结果,可以在后面的 then 中的 fun1 中接收到
- 当 return 123,后面方法的参数就接收到 123
- 当 return ‘hello’,后面方法的参数就接收到 ‘hello’
- 没有 return ,后面方法的参数就接收到 undefined
不过一般是不会 return 数字或者字符串,真正有用的是
return 一个 Promise 对象
-
当then的 fun1 中 return 一个promise 对象1,下个链式的 then 中的 fun1 就是这个 promise 对象1的 resolve(data),在 then 的 fun2 中return 一个 promise 对象2,下个链式的 then 中的 fun2 就是这个 promise 对象2的reject(data)
var fs = require('fs')
var p1 = new Promise(function(resolve,reject){
fs.readFile('./txt/a.txt',function(err,data){
if(err){
console.log("run p1 reject")
reject(err)
}else{
console.log("run p1 resole")
resole(data.toString())
}
})
})
var p2 = new Promise(function(resole,reject){
fs.readFile('./txt/b.txt',function(err,data){
if(err){
console.log("run p2 reject")
reject(err)
}else{
console.log("run p2 resole")
resole(data.toString())
}
})
})
p1.then(function(data){
// 对应的是p1的resolve()
//1. return 123
//2. return 'hello'
//3 不return
//4. return p2 (p2是个promise对象)
},function(data){
// 对应的是p1的reject()
})
.then(function(data){
// 1. console.log(‘data ==’+data) ===> data==123
// 2. console.log(‘data ==’+data) ===> data==hello
// 3. console.log(‘data ==’+data) ===> data==undefined
// 4. console.log(‘data ==’+data) ===> data==p2中resolve(d)的实参 d,
当前该函数就是p2中resolve(d)的定义
})
复制代码
如下图:
例子:读取文件a的内容后再读取文件b的内容,然后再获取文件c的内容1. 如果不使用 promise容易,一般的方法是回调嵌套,即回调地狱
var fs = require('fs')
fs.readFile('./txt/a.txt',function(err,data){
if(err){
console.log('文件a读取失败')
}else{
console.log(data.toString())
fs.readFile('./txt/b.txt',function(err,data){
if(err){
console.log('文件b读取失败')
}else{
console.log(data.toString())
fs.readFile('./txt/c.txt',function(err,data){
if(err){
console.log('文件b读取失败')
}else{
console.log(data.toString())
}
})
}
})
}
})
复制代码
2. 使用 promise 容器,未封装读取文件
var fs = require('fs')
var p1 = new Promise(function(resole,reject){
fs.readFile('./txt/a.txt',function(err,data){
if(err){
console.log("run p1 reject")
reject(err)
}else{
console.log("run p1 resole")
resole(data.toString())
}
})
})
var p2 = new Promise(function(resole,reject){
fs.readFile('./txt/b.txt',function(err,data){
if(err){
console.log("run p2 reject")
reject(err)
}else{
console.log("run p2 resole")
resole(data.toString())
}
})
})
var p3 = new Promise(function(resole,reject){
fs.readFile('./txt/c.txt',function(err,data){
if(err){
console.log("run p3 reject")
reject(err)
}else{
console.log("run p3 resole")
resole(data.toString())
}
})
})
p1.then(function(data){
console.log('p1 then resolved',data)
return p2
})
.then(function(data){
console.log('p2 then resolve',data)
return p3
})
.then(function(data){
console.log('p3 then resolve',data)
})
复制代码
3. 使用 promise 容器,对读取文件进行封装
var fs = require('fs')
function pReadFile(url){
return new Promise(function(resolve,reject){
fs.readFile(url,function(err,data){
if(err){
reject(err)
}else{
resolve(data.toString())
}
})
})
}
var pRF = pReadFile('./txt/a.txt')
pRF.then(function(data){
console.log('run resolve fun',data)
return pReadFile('../txt/b.txt')
},function(err){
console.log('run reject fun','a文件读取失败')
return pReadFile('../txt/b.txt')
})
.then(function(data){
console.log(data)
return pReadFile('./txt/c.txt')
},function(err){
console.log('run reject fun','b文件读取失败')
return pReadFile('./txt/c.txt')
})
.then(function(data){
console.log('run resolve fun',data)
},function(err){
console.log('run reject fun','c文件读取失败')
})
复制代码
转载于:https://juejin.im/post/5cc7bc4d5188252518356a8c
最后
以上就是深情小甜瓜为你收集整理的解决异步编程多层嵌套问题 ==》Promise容器的全部内容,希望文章能够帮你解决解决异步编程多层嵌套问题 ==》Promise容器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复