ES6中的Promise、async、await

/* 二、什么是Promise(一)
    从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。promise有三种状态:
     pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
     为了解决回调地狱的问题,出现了promise对象,*/

         $.ajax({
             url: 'https://xxxx/',
             type: 'POST',
            data: {
                 username: 'sdsd',
                 password: '123123'
             },
                 success: function (res) {
                     $.ajax({
                        url: 'https://xxxxx',
                         type: 'GET',
                        succes: function (res) { 
                              $.ajax({
                                   url: 'https://xxxxx',
                                 type: 'GET',
                                    data: {
                                        movieId: $(this).data('id')
                                    },
                                    success: function (res) { 
                                      var data = res.data;
                                 }
                     })

           }
        });

/* Promise的构造函数接收一个参数:函数,并且这个函数需要传入两个参数:
resolve :异步操作执行成功后的回调函数
reject:异步操作执行失败后的回调函数 */

let p = new Promise((resolve, reject) => {
    //做一些异步操作
    setTimeout(() => {
        console.log('执行完成');
        resolve('我是成功!!');
    }, 2000);


/* 
then 链式操作的用法  
所以,从表面上看,Promise只是能够简化层层回调的写法,而实质上,
Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,
它比传递callback函数要简单、灵活的多。所以使用Promise的正确场景是这样的
 */
p.then((data) => {
    console.log(data);
})
.then((data) => {
    console.log(data);
})
.then((data) => {
    console.log(data);
});

// reject的用法 :把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。看下面的代码。

let p = new Promise((resolve, reject) => {
        //做一些异步操作
      setTimeout(function(){
            var num = 6; 
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字太大了');
            }
      }, 2000);
    });
    p.then((data) => {
            console.log('resolved',data);
        },(err) => {
            console.log('rejected',err);
        }
    );

// then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,
// 第二个对应reject的回调。所以我们能够分别拿到他们传过来的数据。

// catch的用法

// 我们知道Promise对象除了then方法,还有一个catch方法,它是做什么用的呢?其实它和then的第二个参数一样,用来指定reject的回调。用法是这样:
p.then((data) => {
    console.log('resolved',data);
}).catch((err) => {
    console.log('rejected',err);
});

// 效果和写在then的第二个参数里面一样。不过它还有另外一个作用:
// 在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。请看下面的代码:

p.then((data) => {
    console.log('resolved',data);
    console.log(somedata); //此处的somedata未定义
})
.catch((err) => {
    console.log('rejected',err);
});

/* 在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。
如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。也就是说进到catch
方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能 */

/* 
三、理解 JavaScript 的 async/await

    任意一个名称都是有意义的,先从字面意思来理解。async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 
    async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。

    用 setTimeout 模拟耗时的异步操作,先来看看不用 async/await 会怎么写*/

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}

takeLongTime().then(v => {
    console.log("got", v);
});


//如果改用 async/await 呢,会是这样

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}

async function test() {
    const v = await takeLongTime();
    console.log(v);
}

test();


//async/await 的优势在于处理 then 链

// promise方法
let p1 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve('我是p1')
    },4000)
})
let p2 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve('我是p2')
    },200)
})
let p3 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve('我是p3')
    },200)
})
// 想让p1完成后再执行P2再执行P3
// 数量太多只能循环嵌套
p1.then((res) => {
    console.log(res);
    p2.then((res) => {
        console.log(res);
        p3.then((res) => {
            console.log(res);
        })
    })
})

// async  await语法糖
let a1=()=>{
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('我是a1')
        },4000)
    })
} 
let a2=()=>{
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('我是a2')
        },40)
    })
} 
let a3=()=>{
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve('我是a3')
        },40)
    })
} 
// 想让a1完成后再执行a2再执行a3
//能避免回调
async function asy(){
    await a1().then((res) => {console.log(res)});
    await a2().then((res) => {console.log(res)});
    await a3().then((res) => {console.log(res)});
}
asy();


        /*错误处理
        在async函数里,无论是Promise reject的数据还是逻辑报错,都会被默默吞掉,
        所以最好把await放入try{}catch{}中,catch能够捕捉到Promise对象rejected的数据或者抛出的异常
        */
        const makeRequest = () => {
            try {
              getJSON()
                .then(result => {
                  // JSON.parse可能会出错
                  const data = JSON.parse(result)
                  console.log(data)
                })
                // 取消注释,处理异步代码的错误
                // .catch((err) => {
                //   console.log(err)
                // })
            } catch (err) {
              console.log(err)
            }
          }

          const makeRequest = async () => {
            try {
              // this parse may fail
              const data = JSON.parse(await getJSON())
              console.log(data)
            } catch (err) {
              console.log(err)
            }
          }

          const makeRequest = async () => {

              // this parse may fail
              const data = JSON.parse(await getJSON()).catch(err =>{
                console.log(err)
              })
              console.log(data)
          }
        }
)

 

posted @ 2021-10-12 09:07  赵永强  阅读(211)  评论(0编辑  收藏  举报