当前位置:网站首页>回调地狱和promise

回调地狱和promise

2022-08-11 11:52:00 -加油

根据setTimeout的延迟时间,会依次执行奶茶、火锅、唱歌、看电影。这不是我想要的顺序。

function getTea(fn){
    
    setTimeout(()=>{
    
        fn('奶茶')
    },500)
}
function getHotpot(fn){
    
    setTimeout(()=>{
    
        fn('火锅')
    },600)
}
function getSing(fn){
    
    setTimeout(()=>{
    
        fn('唱歌')
    },700)
}
function getfilm(fn){
    
    setTimeout(()=>{
    
        fn('看电影')
    },1000)
}
//统一处理数据的方法
function fn(data){
    
    console.log(data);
}
getfilm(fn)
getSing(fn);
getHotpot(fn);
getTea(fn);

我想先看电影,唱歌、火锅、奶茶,就需要一层一层嵌套实现。就会造成可怕的回调地狱,层数越多维护起来越麻烦。

function getTea(fn){
    
    setTimeout(()=>{
    
        fn('奶茶')
    },500)
}
function getHotpot(fn){
    
    setTimeout(()=>{
    
        fn('火锅')
    },600)
}
function getSing(fn){
    
    setTimeout(()=>{
    
        fn('唱歌')
    },700)
}
function getfilm(fn){
    
    setTimeout(()=>{
    
        fn('看电影')
    },1000)
}
getfilm(function(data){
    
    console.log(data);
    getSing(function(data){
    
        console.log(data);
        getHotpot(function(data){
    
            console.log(data);
            getTea(function(data){
    
                console.log(data);
            })
        })
    })
})

办法:使用promise解决异步问题,比回调地狱更好维护。

//每个函数调用后返回的都是promise对象
function getTea(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            //调用resolve把数据传出去
            resolve('奶茶')
        },500)
    })
}
//每个函数调用后返回的都是promise对象
function getHotpot(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            resolve('火锅')
        },600)
    })
}
//每个函数调用后返回的都是promise对象
function getSing(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            resolve('唱歌')
        },700)
    })
}
//每个函数调用后返回的都是promise对象
function getfilm(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            resolve('看电影')
        },1000)
    })
}
// getfilm(); 返回值是一个promise对象 直接用then
getfilm().then(function(data){
    
    console.log(data);
    //then 里面写一个return 一个还想调的promise对象
    return getSing();
}).then(function(data){
    
    console.log(data);
    return getHotpot();
}).then(function(data){
    
    console.log(data);
    return getTea();
}).then(function(data){
    
    console.log(data);
})

可是看起来也没有化繁为简,一堆的then。
使用async函数

function getTea(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            //调用resolve把数据传出去
            resolve('奶茶')
        },500)
    })
}
function getHotpot(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            resolve('火锅')
        },600)
    })
}
function getSing(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            resolve('唱歌')
        },700)
    })
}
function getfilm(){
    
    return new Promise(function(resolve){
    
        setTimeout(()=>{
    
            resolve('看电影')
        },1000)
    })
}
//将异步实现效果为同步
async function fn(){
    
    //getfilm() 返回值是promise对象,
    //用await直接获取 resolve传递出来的异步数据。
    //而之前我们用then 才能拿到数据data。then(function(data){})
    let film  = await getfilm();
     //必须等待await结束后才继续执行下面代码
    console.log(film);
    //相当于实现同步了
    let sing = await getSing();
    console.log(sing);
    let hot = await getHotpot();
    console.log(hot);
    let tea = await getTea();
    console.log(tea);
}
fn();

可以任意先做什么就做什么,先log谁就log谁

async function fn(){
    
    let film  = await getfilm();
    let sing = await getSing();
    let hot = await getHotpot();
    let tea = await getTea();
    console.log(sing);
    console.log(tea);
    console.log(hot);
    console.log(film);
}
fn();

关于promise:
1、没有resolve、没有reject
不会调用then或者catch。

let p = new Promise(()=>{
    
    //函数里面是同步代码
    console.log('同步执行代码');
})
//只有resolve才会执行then
p.then(()=>{
    
    console.log('then');
})
console.log('同步2');

输出 同步执行代码、同步2

2、resolve没有参数
没有参数也就是没有传数据

let p = new Promise((resolve)=>{
    
    //函数里面是同步执行代码
    console.log('同步执行代码');
    resolve();//有then就会执行
})
//只有resolve才会执行then
p.then(()=>{
    
    console.log('then微任务');
})
console.log('同步2');

注意then是异步的微任务,等待同步任务完成后,才执行微任务。
依次输出同步执行代码、同步2、then微任务。

3、resolve有参数

let p = new Promise((resolve)=>{
    
    //函数里面是同步代码
    console.log('同步执行代码');
    resolve('参数data');
})
//只有resolve才会执行then
p.then((data)=>{
    
    console.log('then微任务');
    console.log(data);
})
console.log('同步2');

注意then是异步的微任务,等待同步任务完成后,才执行微任务。
依次输出同步执行代码、同步2、then微任务、参数data。

3、有resolve、reject。
resolve则执行then、reject则执行catch。且改变不可逆。
当isPass = true,调用resolve。
当为false,调用reject。

        const isPass = true;
        const p = new Promise((resolve,reject)=>{
    
            if(isPass){
    
                resolve("通过了")
            }else{
    
                reject("没有通过哦")
            }
        });
        p.then(grade =>{
    
                  console.log(`你的四六级结果是,${
      grade}`);
              })
         .catch(grade =>{
    
                  console.log(`你的四六级结果是,${
      grade}`);
              })

在promise对象p 加上finally,不管什么情况,都会调用

              .finally(() =>{
    
                  console.log("不管怎么样那还是要吃大餐的");
              });

关于async
1、async函数返回的是promise对象

async function fun1(){
    
    return  20
}
//acync返回的是promise对象
console.log(fun1());
//fun1、fun2 函数是等价的
function fun2(){
    
    return new Promise((resolve)=>{
    
        resolve(20)
    })
}
console.log(fun2());

2、和await配合在例子也提过了。
练习:

console.log('start1');
async function f1(){
    
    await f2();//立即去执行f2函数
    //awaitf2(); 的后面相当于 then
    //将console.log('2');放入微任务队列
    console.log('2');
}
async function f2(){
    
    console.log('3');
}
f1();
setTimeout(function(){
    
    console.log(4);
},500)
console.log(5);
setTimeout(function(){
    
    console.log(6);
},0)
new Promise(resolve=>{
    
    console.log(7);
    resolve();
}).then(function(){
    
    console.log(8);
})
console.log(9);
process.nextTick(()=>{
    
    console.log('process.nextTick');
})
new Promise(resolve=>{
    
    console.log(10);
    resolve();
}).then(function(){
    
    console.log(11);
})
console.log('end');

依次输出start1、3、5、7、9、10、end、process.nextTick、2、8、11、6、4。

总结:
1、同步
2、process.nextTick
3、异步(4、微任务:promise.then…。 5、宏任务:计时器、ajax,读取文件…)

补充:
promise链式调用

      <script>
        new Promise((resolve,reject)=>{
    
            console.log(1);
            resolve(100)
        })
        .then(v=>{
    
            new Promise((resolve,reject)=>{
    
                console.log(2+',v:'+v);
                resolve(200)
            }).then(v=>{
    
                console.log(3+',v:'+v);
            }).then(v=>{
    
                console.log(4+',v:'+v);
                return 300
            }).then(v=>{
    
                console.log(5+',v:'+v);
                return 400
            })
        })
        .then(v=>{
    
            console.log(6+',v:'+v);
        })
    </script>

链式调用,then一定依赖同一个promise的上一个then中return的值。
在这里插入图片描述
结果:
第一个then中没有return给第二个then,而且第一个then中有promise,它是异步操作
在这里插入图片描述
加上return 后,执行完第一个then才到第二个then。
在这里插入图片描述
结果:

在这里插入图片描述
关于reutrn的值:必须是当前then的return 的promise的最后一个then一定要有return。
在这里插入图片描述
有return:
再怎么嵌套都要保证最后一个then有return。
在这里插入图片描述
绕啊绕

    <script>
        new Promise((resolve,reject)=>{
    
            resolve(100)
        })
        .then(v=>{
    
            return new Promise((resolve,reject)=>{
    
                console.log(1+',v:'+v);
                resolve(200)
            }).then(v=>{
    
                console.log(2+',v:'+v);
                return 300
            }).then(v=>{
    
                console.log(3+',v:'+v);
                return 3
            }).then(v=>{
    
                console.log(33+',v:'+v);
                return 33
            }).then(v=>{
    
                console.log(333+',v:'+v);
                return 333
            }).then(v=>{
    
                console.log(3333+',v:'+v);
                return 400
            })
        })
        .then(v=>{
    
            return new Promise((resolve,reject)=>{
    
                console.log(4+',v:'+v);
                resolve(500)
            }).then(v=>{
    
                console.log(5+',v:'+v);
                return 600
            }).then(v=>{
    
                console.log(6+',v:'+v);
                return 6
            }).then(v=>{
    
                console.log(66+',v:'+v);
                return 66
            }).then(v=>{
    
                console.log(666+',v:'+v);
                return 666
            }).then(v=>{
    
                console.log(6666+',v:'+v);
                return 700
            })
        })
        .then(v=>{
    
            return new Promise((resolve,reject)=>{
    
                console.log(7+',v:'+v);
                resolve(400)
            }).then(v=>{
    
                console.log(8+',v:'+v);
                return 800
            }).then(v=>{
    
                console.log(9+',v:'+v);
                return 9
            }).then(v=>{
    
                console.log(99+',v:'+v);
                return 99
            }).then(v=>{
    
                console.log(999+',v:'+v);
                return 999
            }).then(v=>{
    
                console.log(9999+',v:'+v);
                return 1000
            })
        })
        .then(v=>{
    
            return new Promise((resolve,reject)=>{
    
                console.log(10+',v:'+v);
                resolve(1000)
            }).then(v=>{
    
                console.log(11+',v:'+v);
                return 1200
            })
        })
        .then(v=>{
    
            console.log(12+',v:'+v);
        })
    </script>

在这里插入图片描述
结果很顺序
在这里插入图片描述
但是当其中有的没有return,而且还有promise对象时。
把第1个、第2个、第四个的return删掉后

    <script>
        new Promise((resolve,reject)=>{
    
            resolve(100)
        })
        .then(v=>{
    
             new Promise((resolve,reject)=>{
    
                console.log(1+',v:'+v);
                resolve(200)
            }).then(v=>{
    
                console.log(2+',v:'+v);
                return 300
            }).then(v=>{
    
                console.log(3+',v:'+v);
                return 3
            }).then(v=>{
    
                console.log(33+',v:'+v);
                return 33
            }).then(v=>{
    
                console.log(333+',v:'+v);
                return 333
            }).then(v=>{
    
                console.log(3333+',v:'+v);
                return 400
            })
        })
        .then(v=>{
    
             new Promise((resolve,reject)=>{
    
                console.log(4+',v:'+v);
                resolve(500)
            }).then(v=>{
    
                console.log(5+',v:'+v);
                return 600
            }).then(v=>{
    
                console.log(6+',v:'+v);
                return 6
            }).then(v=>{
    
                console.log(66+',v:'+v);
                return 66
            }).then(v=>{
    
                console.log(666+',v:'+v);
                return 666
            }).then(v=>{
    
                console.log(6666+',v:'+v);
                return 700
            })
        })
        .then(v=>{
    
            return new Promise((resolve,reject)=>{
    
                console.log(7+',v:'+v);
                resolve(400)
            }).then(v=>{
    
                console.log(8+',v:'+v);
                return 800
            }).then(v=>{
    
                console.log(9+',v:'+v);
                return 9
            }).then(v=>{
    
                console.log(99+',v:'+v);
                return 99
            }).then(v=>{
    
                console.log(999+',v:'+v);
                return 999
            }).then(v=>{
    
                console.log(9999+',v:'+v);
                return 1000
            })
        })
        .then(v=>{
    
             new Promise((resolve,reject)=>{
    
                console.log(10+',v:'+v);
                resolve(1000)
            }).then(v=>{
    
                console.log(11+',v:'+v);
                return 1200
            })
        })
        .then(v=>{
    
            console.log(12+',v:'+v);
        })
    </script>

结果有undefined,而且then中有promise异步,执行顺序不一致,不过then所依赖的同级上一个then的return的值不变。
在这里插入图片描述
再补充:

1、fulfilled状态的promise,自动向下找then,在then中返回非promise的值,它会生成状态fulfilled的新promise对象,传入下一个回调函数。

    <script>
        new Promise((resolve,reject)=>{
    
            resolve(100)
        }).then(v=>{
    
            console.log(1+',v:'+v);
            return 200
        }).then(v=>{
    
            console.log(2+',v:'+v);
        }).catch(v=>{
    
            console.log(3+',v:'+v);
        })
    </script>

在这里插入图片描述
2、
rejected状态的promise,自动向下找catch,在catch中返回非promise的值,它会生成状态fulfilled的新promise对象,传入下一个回调函数。

    <script>
        new Promise((resolve,reject)=>{
    
            reject(100)
        }).then(v=>{
    
            console.log(1+',v:'+v);
            return 200
        }).catch(v=>{
    
            console.log(3+',v:'+v);
            return 300
        }).then(v=>{
    
            console.log(4+',v:'+v);
        }).catch(v=>{
    
            console.log(5+',v:'+v);
        })
    </script>

在这里插入图片描述
在这里插入图片描述

3、rejected状态的promise,自动向下找catch,在catch中返回promise对象的值,根据该promise对象的状态决定传入下一个回调函数。

    <script>
        new Promise((resolve,reject)=>{
    
            reject(100)
        }).then(v=>{
    
            console.log(1+',v:'+v);
            return new Promise.reject(200)
        }).then(v=>{
    
           console.log(2+',v:'+v);
        }).catch(v=>{
    
            console.log(3+',v:'+v);
            return new Promise.reject(300)
        }).then(v=>{
    
            console.log(4+',v:'+v);
        }).catch(v=>{
    
            console.log(5+',v:'+v);
        }).catch(v=>{
    
            console.log(6+',v:'+v);
        }).catch(v=>{
    
            console.log(7+',v:'+v);
        })
    </script>

在这里插入图片描述

4、
fulfilled状态的promise,自动向下找then,在then中返回promise对象的值,根据该promise对象的状态决定传入下一个回调函数。

        new Promise((resolve,reject)=>{
    
            resolve(100)
        }).then(v=>{
    
            console.log(1+',v:'+v);
            return new Promise.reject(200)
        }).then(v=>{
    
           console.log(2+',v:'+v);
        }).catch(v=>{
    
            console.log(3+',v:'+v);
        }).then(v=>{
    
            console.log(4+',v:'+v);
        }).catch(v=>{
    
            console.log(5+',v:'+v);
        })
    </script>

在这里插入图片描述
5、抛出错误异常
都会生成rejected状态的promise。

    <script>
        new Promise((resolve,reject)=>{
    
            resolve(100)
        }).then(v=>{
    
            console.log(2+',v:'+v);
            throw new Error('xxx')
        }).catch(v=>{
    
            console.log(3+',v:'+v);
            throw new Error('xxx')
        }).then(v=>{
    
            console.log(4+',v:'+v.message);
        }).catch(v=>{
    
            console.log(5+',v:'+v.message);
        }).catch(v=>{
    
            console.log(6+',v:'+v.message);
        })
    </script>

在这里插入图片描述
在这里插入图片描述

原网站

版权声明
本文为[-加油]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_51040174/article/details/124646230