回调
- 把一个函数A传给另一个函数B调用,那么A就是回调函数
具名回调写法
function 获取用户信息(fn){
fn.call(undefined,'姓名:xxx')
}
function 用户信息(信息){
console.log(信息)
}
获取用户信息.call(undefined,用户信息)
//姓名:xxx
匿名回调写法
function 获取用户信息(fn){
fn.call(undefined,'姓名:xxx')
}
获取用户信息.call(undefined,function(信息){
console.log(信息)
})
多层嵌套的匿名回调(回调地狱)
获取用户信息(function(用户信息){
console.log(用户信息)
保存用户信息(用户信息, function(){
获取另一个用户信息(function(另一个用户信息){
保存用户信息(function(){})
})
})
})
像这种使用多层匿名函数回调的嵌套,就会很难让人读懂你的代码,而这种回调套回调(一般三到五层以上)又称为回调地狱
缺点
- 容易造成回调地狱
- 不知道该怎么使用回调Node/jQuery的回调使用方法都不一样--只能强行背下
Promise
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
作用:
(1)简化回调写法
(2)链式操作
基本用法
Promise是一个构造函数,Promise接收一个参数,这个参数是函数,同时这个参数函数要传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。
1.解决了不知道该如何使用回调问题
promise前面是操作,后面的then是操作的结果,then里面的第一个参数是成功后要做的,第二个是失败后要做的
获取用户信息().then(function(){},function(){})
2.解决了回调地狱
可以不断地then,就不存在嵌套了,永远只有一层
获取用户信息()
.then(打印用户信息)
.then(获取另一个用户信息)
.then(打印用户信息)
使用promise实现上面回调地狱中的案例
function 获取用户信息(){
return new Promise((resolve,reject)=>{
console.log('第一次获取用户信息')
resolve('姓名:方方')
})
}
function 打印用户信息(用户信息){
return new Promise((resolve,reject)=>{
console.log(用户信息)
resolve()
})
}
function 获取另一个用户信息(){
return new Promise((resolve,reject)=>{
//下面的console是同步
console.log('第二次获取用户信息')
//resolve和reject是异步
resolve('姓名:琳琳')
})
}
获取用户信息()
.then(打印用户信息)
.then(获取另一个用户信息)
.then(打印用户信息)
//第一次获取用户信息
//姓名:方方
//第二次获取用户信息
//姓名:琳琳
.then里面的成功函数里面的第一个参数的值就是在resolve()里传入的实参
同样reject里面传入的实参也是then里面的失败函数里面的第一个参数的值
栗子:
function 获取用户信息(name){
return new Promise((resolve,reject)=>{
if(name === 方方'){
console.log('我认识方方')
resolve('方方是一个帅锅')
}else{
console.log('不认识')
reject()
}
})
}
获取用户信息('xx')
.then(
(res)=>console.log(res),
(err)=>console.log('看来他不认识方方')
)
//我认识xx
// xx是一个帅锅
获取用户信息('方方')
.then(
(res)=>console.log(res),
(err)=>console.log('看来他不认识方方')
)
//不认识
// 看来他不认识方方
另外如果你想对一个值进行多次then操作,那么你就需要在每一个成功函数里面的resolve都传入参数,用来获取你上一次的值
比如:
function 获取用户信息(name){
return new Promise((resolve,reject)=>{
if(name === '方方'){
console.log('我认识方方')
resolve(['方方','是个帅锅'])
}else{
console.log('不认识')
reject()
}
})
}
function 获取好友信息(name){
return new Promise((resolve,reject)=>{
if(name === '方方'){
resolve('张三、李四、王五')
}
else{
reject()
}
})
}
function 打印信息(data){
return new Promise((resolve,reject)=>{
console.log(data)
resolve(data[0])
})
}
获取用户信息('方方')
.then(打印信息)
.then(获取好友信息)
.then(打印信息)
//我认识方方
// ["方方", "是个帅锅"]
// 张三、李四、王五
then里面的函数不管是调用了成功函数还是失败函数,它的下一个then都会执行成功的函数,除非你在失败函数里面直接reject。
比如:
function 获取用户信息(name){
return new Promise((resolve,reject)=>{
if(name === '方方'){
console.log('我认识方方')
resolve(['方方','是个帅锅'])
}else{
console.log('不认识')
reject()
}
})
}
function 获取好友信息(name){
console.log('获取好友信息')
return new Promise((resolve,reject)=>{
if(name === '方方'){
resolve('张三、李四、王五')
}
else{
reject()
}
})
}
function 打印信息(data){
return new Promise((resolve,reject)=>{
console.log(data)
resolve(data[0])
})
}
function 打印失败(理由){
console.log('失败理由是'+理由)
}
获取用户信息('琳琳')
.then(打印信息,打印失败)
.then(获取好友信息)
.then(打印信息)
//不认识
// 失败理由是undefined
// 获取好友信息
上面虽然调用了第一个then的失败函数,但是下一个的获取好友这个函数依然会执行,主要是因为我们失败函数里什么也没return,浏览器会默认为我们已经处理好了这个错误,但是我们该如何让浏览器知道我们没搞定这个失败,让下面的成功函数不执行哪?
方法:
1.直接在失败函数里返回一个promise然后调用reject
直接return Promise.reject()
Promise.all()
- Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const newPromise = Promise.all([promise1,promise2,promise3])
await
上面我们通过.then可以拿到成功或者失败的信息,但是then里面其实还是用了回调,有什么方法可以不使用回调哪?
方法:在返回promise的函数之前加一个await
let 用户信息 = await 获取用户信息('方方')
console.log(用户信息)
//["方方", "是个帅锅"]
上面的代码如果不加await拿到的就是一个new Promise(),加上await意思就是等它resolve,那么如果它失败了就会报错,所以我们需要配合try..catch来使用
正确写法
try{
let 用户信息 = await 获取用户信息('琳琳')
console.log(用户信息)
}catch(error){
//失败的理由是
console.log(error)
}
如果你想在一个函数里使用await那么就必须在这个函数前面加async
网友评论