js异步操作的方式

一、promise

// resolve代表成功 reject失败 都是一个函数

let p = new Promise(function(reslove,reject){

    //reslove('成功')  //状态由等待变为成功,传的参数作为then函数中成功函数的实参

    reject('失败')  //状态由等待变为失败,传的参数作为then函数中失败函数的实参

})

//then中有2个参数,第一个参数是状态变为成功后应该执行的回调函数,第二个参数是状态变为失败后应该执行的回调函数。

p.then((data)=>{

    console.log('成功'+data)

},(err)=>{

    console.log('失败'+err)

})

如果then中返回了一个promise 会将promise的结果继续传给第二then中(如果结果是将状态改成成功就走下一个then的成功回调,状态改为失败就走下一个then的失败回调) 

function read( content ) {
    return new Promise(function( reslove,reject ) {
        setTimeout(function(){
                if(content>4){
                    resolve(content)
                }else{
                    reject('小于4')
                }
        },1000)
    })
}

read(1).then(( data )=>{
    console.log(data)
},( err )=>{
    console.log(err) //小于4
    return read(2) //将状态改为了失败
})
.then(( data )=>{
    console.log('data',data)
},( err )=>{
    console.log(err) //小于4
})

catch的用法

catch可以实现错误的捕获 一般写在最后,如果上面有自己的err会走自己的error。如果没有写就会走到catch

let p = new Promise(function(resolve,reject){
    reject('失败')
});

p.then((data)=>{

},(err)=>{
    throw Error('错误')
})
.then((data)=>{

},(err)=>{
    console.log(err+'自己的err') //走自己的(输出:Error: 错误自己的err)
    throw Error('错误自己抛出的')
})
.then((data)=>{
//没有自己的失败处理函数,走catch
}).catch(e=>{
    console.log(e+'公共的err') //输出:Error: 错误自己抛出的公共的err
})

all的用法

Promise.all方法执行后返回的依旧是promise, all两个全成功才表示成功 。

function read(content) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(content)
        }, 1000)
    })
}

let result = Promise.all([read(1), read(2)]);
result.then((data) => {
    console.log(data) //[ 1, 2 ]
})

race的用法

如果先成功了那就成功了, 如果先失败了那就失败了

function read(content) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            if(content>4){
                resolve(content)
            }else{
                reject(content)
            }
        }, 1000*content)
    })
}

let result = Promise.race([read(5), read(2)]);
result.then((data) => {
    console.log('成功'+data)
},(err)=>{
    console.log('失败'+err) //失败2
})

二、async和await

基本用法:

function 摇色子(){
    return new Promise((resolve, reject)=>{
        let sino = parseInt(Math.random() * 6 +1)
        setTimeout(()=>{
            resolve(sino)
        },3000)
    })
}
async function test(){
    let n =await 摇色子()
    console.log(n)
}
test()
  • 获取失败的结果
function 摇色子(猜测){
    return new Promise((resolve, reject)=>{
        let sino = parseInt(Math.random() * 6 +1)
        if(sino > 3){
            if(猜测 === '大'){
                resolve(sino)
            }else{
                reject(sino)
            }
        }else{
            if(猜测 === '大'){
                reject(sino)
            }else{
                resolve(sino)
            }
        }
        setTimeout(()=>{
            resolve(sino)
        },300)
    })
}
async function test(){
    try{
        //把await及获取它的值的操作放在try里
        let n =await 摇色子('大')
        console.log('赢了' + n)
    }catch(error){
      //失败的操作放在catch里
        console.log('输了' + error)
    }
}
test()

前面我们说了,async和await是处理then链的语法糖,现在我们来看看具体是怎么实现的:

假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。我们仍然用setTimeout来模拟异步操作:

 

/**
 * 传入参数 n,表示这个函数执行的时间(毫秒)
 * 执行的结果是 n + 200,这个值将用于下一步骤
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(n) {
    console.log(`step2 with ${n}`);
    return takeLongTime(n);
}

function step3(n) {
    console.log(`step3 with ${n}`);
    return takeLongTime(n);
}

 

现在用 Promise 方式来实现这三个步骤的处理。

 

function doIt(){
    console.time('doIt');
    let time1 = 300;
    step1(time1)
        .then((time2) => step2(time2))
        .then((time3) => step3(time3))  
        .then((result) => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        })
}

doIt();

//执行结果为:
//step1 with 300
//step2 with 500
//step3 with 700
//result is 900
//doIt: 1510.2490234375ms

 

输出结果 result 是 step3() 的参数 700 + 200 = 900doIt() 顺序执行了三个步骤,一共用了 300 + 500 + 700 = 1500 毫秒,和 console.time()/console.timeEnd() 计算的结果一致。

如果用 async/await 来实现呢,会是这样:

 

async function doIt() {
    console.time('doIt');
    let time1 = 300;
    let time2 = await step1(time1);//将Promise对象resolve(n+200)的值赋给time2
    let time3 = await step1(time2);
    let result = await step1(time3);
    console.log(`result is ${result}`);
    console.timeEnd('doIt');
}

doIt();

//执行结果为:
//step1 with 300
//step2 with 500
//step3 with 700
//result is 900
//doIt: 1512.904296875ms

 

显然我们用async/await简单多了

await 表达式的运算结果取决于它等的东西。

如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。

如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

function testAsy(x){
   return new Promise(resolve=>{setTimeout(() => {
       resolve(x);
     }, 3000)
    }
   )
}
async function testAwt(){    
  let result =  await testAsy('hello world');
  console.log(result);    // 3秒钟之后出现hello world
  console.log('tangj')   // 3秒钟之后出现tangj
}
testAwt();
console.log('tangSir')  //立即输出tangSir

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值