JS异步全解02:Promise,async-await

Promise

三种状态

  • pending -> resolved -> 或pending -> rejected

  • 变化不可逆

const p1 = new Promise((resolve, reject) => {

})

console.log("p1", p1)

const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve();
    })
})

console.log("p2", p2)
setTimeout(() => console.log("p2-setTimeout", p2))


const p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject();
    })
})

console.log("p3", p3)
setTimeout(() => console.log("p3-setTimeout", p3))

在这里插入图片描述

状态的表现

  • pending状态不会触发then和catch
  • resolve会触发then和catch
  • reject会触发catch

then和catch的改变状态

  • then正常返回resolved,里面有报错则返回rejected
  • catch正常返回resolved,里面有报错则返回rejected
const p1 = Promise.resolve().then(() => {
    return 100;
});
console.log("p1", p1);

p1.then(() => {
    console.log("p1 then");
});

const p2 = Promise.resolve().then(() => {
    throw new Error("then error");
});
console.log("p2", p2);

p2.then(() => {
    console.log("p2 then");
}).catch((err) => {
    console.log("p2 catch error", err);
});


const p3 = Promise.reject("p3 error").catch(err => {
    console.error(err);

});
console.log("p3", p3);  // resolved 触发一个then回调
p3.then(() => {
    console.log("p3 then");
});

const p4 = Promise.reject("p3 error").catch(err => {
    throw new Error("p4 catch error");

});
console.log("p4", p4);  // rejected 触发一个catch回调
p4.then(() => {
    console.log("p4 then"); // 不会打印
}).catch((err) => {
    console.log("p4 catch", err);
});

在这里插入图片描述

Promise题目

Promise.resolve().then(() => {
    console.log(1);
}).catch(() => {
    console.log(2);
}).then(() => {
    console.log(3);
})
12
Promise.resolve().then(() => {	// 报错返回rejected
    console.log(1);
    throw new Error("error1");
}).catch(() => {	// 没报错返回resolved状态
    console.log(2);
}).then(() => {
    console.log(3);
})
123
Promise.resolve().then(() => {
    console.log(1);
    throw new Error("error1");
}).catch(() => {
    console.log(2);
}).catch(() => {
    console.log(3);
})
12

async-await

异步的发展

  1. 异步回调 callback 和hell

问题:回调地狱

  1. Promise then catch 链式调用,但是也是基于回调函数

  2. async-await 是同步语法,彻底消灭回调函数

async-await基本用法

  1. await后面跟Promise函数
  2. await后面跟async函数

async-await与Promise的关系

  • async-await是消灭异步回调的最终手段

  • 但是和Promise并不互斥,反而相辅相成

  • 执行async函数 返回的一定是Promise对象

  • try-catch可捕获异常,取代了.catch

async 执行必定返回Promise对象

async function fn1() {
    // return "fn1" // 相当于 return Promise.resolve("fn1")
    return Promise.resolve(200);
}
const res1 = fn1();
console.log(res1);

res1.then(data => {
    console.log("res1 data", data);
});

await 相当于then()

(async function () {
    const p1 = Promise.resolve(300);
    const data = await p1;
    console.log("data", data);
})();
(async function () {
    const p1 = await 400; // 相当于 await Promise.resolve(400)
    const data = await p1;
    console.log("data", data);
})();
(async function () {
    const p1 = await fn1();	
    const data = await p1;
    console.log("data", data);
})();

try-catch

(async function () {
    const p4 = Promise.reject("err");
    try{
        const res = await p4;
        console.log(res);
    }catch (err) {
        console.log("err1", err)
    }
})();

(async function () {
    const p5 = Promise.reject("err");
    const res = await p4;   // 此时是rejected状态,不会执行,try-catch可解决
    console.log(res)
})();

异步的本质还是回调函数

  • js是单线程,异步是基于event loop
  • async await 只是一个语法糖
async function async1() {
    console.log("async1 start");
    await async2();
    // await 的后面行代码都会变为异步
    console.log("async1 end");
}

async function async2() {
    console.log("async2");
}

console.log("script start");
async1();
console.log("script end");

打印

script start
async1 start
async2
script end
async1 end

先执行完同步代码

启动event loop

执行异步代码

增加一个async函数

async function async1() {
    console.log("async1 start");
    await async2();
    console.log("async1 end");
    await async3();
    console.log("async1 end 2");
}

async function async2() {
    console.log("async2");
}

async function async3() {
    console.log("async3");

}

console.log("script start");
async1();
console.log("script end");

打印

script start
async1 start
async2
script end
async1 end
async3
async1 end 2

for-of 的应用场景

  • for-in是常规的同步遍历
  • for-of 常用于异步的遍历

普通异步的遍历代码如下

function muti(num) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(num * num);
        }, 1000);
    });
}

const nums = [1, 2, 3];

nums.forEach(async (i) => {
    const res = await muti(i);
    console.log(res);
});

1s后全部同时打印出来

如果需要一次一个一秒打印出来时就需要用到for-of

注意await需要使用async 函数包裹才能执行

function muti(num) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(num * num);
        }, 1000);
    });
}

const nums = [1, 2, 3];

!(async function () {
    for (let i of nums) {
        const res = await muti(i);
        console.log(res);
    }
})();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值