pormise和async pormise

pormise和async
pormise

1.异步问题

假设现在我刚认识你,需要和你说话,但是我普通话不够标准,需要间隔一秒钟才能说一句话,以此让你可以慢慢思考。这样的话我们就需要用到定时器。

最沙雕的代码如下:

            setTimeout(
                function(){
                    console.log('你好,我是saoge');
                    setTimeout(
                        function(){
                            console.log('很高兴认识你');
                            setTimeout(
                                function(){
                                    console.log('交个朋友吧');
                            },1000)
                    },1000)
                },1000)

但是这种代码,是根本没有可读性的。因此我们还有另一种写法。

 function helloOne(next){
                setTimeout(function(){
                    console.log('你好,我是saoge');
                    next();
                },1000)
            }
            
            function helloTow(next){
                setTimeout(function(){
                    console.log('你好,很高兴认识你');
                    next();
                },1000)
            }
​
            function helloThree(){
                setTimeout(function(){
                    console.log('交个朋友吧');
                },1000)
            }
​
        helloOne(function(){
            helloTow(function(){
                helloThree()
            })
        })

用回调函数来实现代码看上去会有逻辑性的多,但是在调用的时候也会存在层层嵌套的问题,如果这个时候我是个话痨,要和你说很多据话,那么用回调函数写出来的代码也是相当恐怖的,而且采用这种方式并不能很方便的改变执行的顺序等。总而言之就是因为总总不好,所以出现了更好的方式promise。

使用Promise

使用new来创建一个Promise的实例。

 var promise = new Promise(function(resolve,reject){
            setTimeout(function(){
                    resolve('你好,我是saoge');
                    reject(new Error('发生错误'));
                      // if(false){
                    //  resolve('你好,我是saoge');
                    // }else{
                    //  reject(new Error('发生错误'))
                    // }
            },1000)
        })
    promise.then(function(data){
        console.log(data);
    },function(err){
        console.log(err)
    })
    //使用catch
    promise.then(function(data){
        console.log(data);
    }).catch(function(err){
        console.log(err);
    })

我们来一步一步的分析上述案例。

在上述实例中,Promise传入了两个形参 resolve 和 reject 这两个参数的回调,代表成功和失败,如果执行正常,就调用resolve,否则就调用reject。上代码:

var promise = new Promise(function(resolve,reject){
        //成功时调用resolve
        //失败时调用reject
    })

同时,promise实例具有then方法,then方法接受两个参数,第一个参数时resolve执行成功的回调,第二个参数reject 是执行失败的回调。

因此,在上述案例中,最终会输出 "你好我是骚哥"

我们可以用if语句来模拟一下执行失败的情况,这个时候输出的就是 Error:发生错误

同时,Promise实例还提供了一个catch()方法,该方法和then()方法接收的第二个参数一样,用来执行reject的回调。

var promise = new Promise(function(resolve,reject){
        //成功时调用resolve
        //失败时调用reject
    })
    promise.then( resolve的回调 , reject 的回调(可选)  );
    promise.catch(reject的回调);

我们用Promise来实现一下最初对话的案例。

 function helloOne() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('你好,我是saoge');
                        next();
                    }, 1000)
                })
        }
        function helloTwo() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('你好,很高兴认识你');
                        next();
                    }, 1000)
                })
        }
        function helloThree() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('交个朋友吧');
                        next();
                    }, 1000)
                })
        }
        helloOne().then(helloTwo).then(helloThree);

和使用回调的区别在于,我们将要执行的代码放在了Promise实例中,这样,在我们最后需要执行的时候,只需要用then()方法去调用即可,语法结构简单,即使我想说再多的话也不会造成代码结构混乱。且在这里使用了Promise方法之后,如果是我想要改变代码执行顺序的话只需要改变then()方法传入的值即可。

异步之间传参

function hello(){
            var text='你好,我是saoge';
            setTimeout(function(){
                console.log(text);
                say(text);
            },1000)
        }
        function say(text){
            setTimeout(function(){
                console.log(text)
            },1000)
        }
        hello();

Promise在执行成功的时候,会调用resolve,因此,我们就可以用resolve来传值。

 var pro = new Promise((resolve, reject) => {
            setTimeout(function() {
                var text = '你好,我是saoge';
                console.log(text);
                resolve(text);
            }, 1000)
        })
​
        pro.then(function(data) {
            setTimeout(function() {
                console.log(data);
            }, 1000)
        })

需要等待多个函数执行完毕再执行时:Promise.all()

function helloOne() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('你好,我是saoge');
                        next();
                    }, 1000)
                })
        }
        function helloTwo() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('你好,很高兴认识你');
                        next();
                    }, 2000)
                })
        }
        function helloThree() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('交个朋友吧');
                        next();
                    }, 3000)
                })
        }
        Promise.all([helloOne(),helloTwo(),helloThree()]).then(function(){
            setTimeout(function(){
                console.log('可以吗?')
            },1000)
        });

上面这段代码就会先在一秒钟我说出你好,我是骚哥。然后再过一秒钟我说你好,很高兴认识你。再过一秒钟说出交个朋友吧,我们可以看到在then()方法里面有一个函数,是一秒钟之后询问你可以吗?而这句话执行的时间是第四秒。也就是Promise.all中的函数执行完成之后再去执行hten()方法中的语句。

Promise.race()

  function helloOne() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('你好,我是saoge');
                        next();
                    }, 1000)
                })
        }
        function helloTwo() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('你好,很高兴认识你');
                        next();
                    }, 2000)
                })
        }
        function helloThree() {
            return new Promise(
                function(next) {
                    setTimeout(function() {
                        console.log('交个朋友吧');
                        next();
                    }, 3000)
                })
        }
        Promise.race([helloOne(),helloTwo(),helloThree()]).then(function(){
            setTimeout(function(){
                console.log('可以吗?')
            },1000)
        });

看上面这个例子,执行一秒之后输出“你好,我是骚哥”,然后再过一秒钟会输出两句话,“你好,很高兴认识你”,“可以吗?”,最后再输出“交个朋友吧” 可以看出,在helloOne执行完毕之后,then()中的代码就开始执行了,和Promise.all()的不同就在于,只要有一个执行成功就去执行hten()中的代码。

 

async

1.async干了什么

 async function helloOne(){
            setTimeout(function(){
                return("你好,我是骚哥");
            },1000)
        }
        console.log(helloOne())  //Promise {<fulfilled>: undefined}

async 返回的是一个Promise对象。

  async function helloOne(){
            setTimeout(function(){
                return("你好,我是骚哥");
            },1000)
        }
        console.log(helloOne());    //Promise {<fulfilled>: undefined}
        helloOne().then(function(data){ 
            console.log(data) //undefined
        })

我们尝试用then()去获取async函数中的值,但是返回的是undefined,且两个输出语句是同时执行的,所以说then()中的函数还没有等到异步函数执行完便执行了,因此这里和Promise不太一样。

  function helloOne() {
                return new Promise((resolve,reject)=>{
                    setTimeout(
                        function(){
                            resolve( '你好,我是saoge');
                        }, 1000)
                });
            }
            function helloTwo(){
                setTimeout(
                        function(){
                            return '拜拜';
                        }, 1000)
                }
             async function say(){
                var one = await helloOne()
                console.log(one)  //你好,我是saoge
                var two = await helloTwo()
                console.log(two) //undefined
            }
            say()

直接看代码,可以发现,如果await 后面跟的是一个Promise对象,那么将会等到Promise对象resolve,然后将resolve的值作为表达式的结果。如果不是以恶搞promise对象,那么await的运算结果就是此时传入的东西,兵不会有其他作用。