js中的异步/同步任务、js中的promise、async/await 用法、什么是函数的回调地狱(保姆级教程一)

一、js中的 同步/异步 相关

1.1 基本概念

1、同步任务: 按顺序一个一个往下执行。

但同时,有些功能的代码执行时间比较长。比如:定时器 setTimeout() 函数,就可以设置一段延时执行的代码,那在这段空闲时间内,是不希望程序阻塞的,而是继续往下执行,这种情况下,如果还将 setTimeout() 设置为同步任务的话,显然就不合理了。---->

所以在 js 中除了同步任务外,还有异步任务。js 中常见的异步任务有:setTimeout() 定时器、Ajax

2、异步任务: 在执行的时候,不会跟同步任务一样按顺序走。而是当一个异步任务被创建之后,它会在一个特殊的队列中进行等待(任务队列),等待以后通过一定的机制,再添加到主线程中执行。

重点:异步任务的执行一定是在我们当前已经触发了这些同步任务之后去执行的。

1.2 案例说明

举个例子:

===代码一:
console.log('任务1:同步')
console.log('任务2:同步')
console.log('任务3:同步')
// function(){} 可以用箭头函数代替 ()=>{}
setTimeout(function (){
    console.log('任务4:异步')
},1000)
============输出:
任务1:同步
任务2:同步
任务3:同步
任务4:异步


===代码二:
console.log('任务1:同步')
console.log('任务2:同步')
setTimeout(function (){
    console.log('任务4:异步')
}) //不写定时器时间,默认为最小时间
console.log('任务3:同步')
============输出:
任务1:同步
任务2:同步
任务3:同步
任务4:异步

分析:

代码一:写了一个定时器,开始的时候是同步任务先触发(其中:任务1、2、3一定是按照顺序来执行的),然后再开始触发异步任务。

代码二:由 setTimeout 触发的异步任务,它内部的代码并不会在这个位置执行。因为异步任务会在当前存在的同步任务都执行完毕后再被触发。

注意: 跟定时器的时间没有关系,时间决定了:如果你存在多个异步任务,决定了异步任务之间的一个执行顺序:

二、Promise

2.1 上面案例带来的问题 ---- 回调地狱

1、思考:代码二中,这样的编写程序会有什么影响?----> 首先:在实际任务中,每个任务都可能是复杂的代码。其次:如果说任务3 需要 依赖于 任务4 处理后的结果,那怎么办?

setTimeout(function (){
    console.log('任务4:异步')
    console.log('任务3:同步')
})

那我直接把任务3 放到任务4 中,那也还行。假如在执行任务3 时,发现它后面还有异步任务,这时怎么办呢?----> 直接嵌套

setTimeout(function (){
    console.log('任务4:异步')
    console.log('任务3:同步')
    setTimeout(function (){
        console.log('任务5:异步')
        console.log('任务6:异步')
	})
})

直接嵌套的方式肯定不行 ----> 会导致代码出现很多的嵌套层数(也叫做函数的回调地狱

方式:所以为了解决这个问题,需要用到 Promise。----> 能够 将这种复杂的嵌套式的异步结构 书写为 一种更接近于同步的写法

2.2 promise的基本使用

2、使用:

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

})
console.log(p1)

Promise 是个类,直接通过 new 创建 Promise 实例,其中参数是一个回调函数,并且回调函数有两个参数:

① resolve:异步任务执行成功的一个工具

② reject:异步任务执行失败的一个工具

通过先打印 p1:

  • 每个 Promise 对象都具备 状态 这个概念,此时 pending 就是等待的状态,也就是说现在 promise 对象并没有被分配一个状态(等待是默认状态)

    成功、失败、等待怎么在实际开发中理解?----> 任务执行肯定有成功或失败,比如说像服务端请求数据,拿到了一个正确数据,那就成功,否则就失败。也有可能请求发出去了,服务端没有给响应,这个过程中判定不了是成功还是失败,此时就处于等待的状态。

然后再去使用 resolve、reject 做个观察:其中调用 resolve()、reject(),就触发了 resolve、reject 这两个工具:

我们创建的 promise 实例(也就是 p1),它其实就标记了在 new promise 中设计的异步任务的一个处理结果,所以可以利用它进行后续处理。

Promise 提供了三个常用的方法:

方法含义
then成功后只要是成功的状态(fulfilled)就自动调用
catch失败后rejected 状态就自动调用
finally都会执行无论失败与否,最后都会执行
const p1 = new Promise((resolve, reject) => {
    // resolve("成功后的数据")
    reject("失败后的数据")
})
p1.then(data => {
    /* 这个data可自命名,含义:就是成功后,传递的结果
    data怎么来?就是上面调用resovle中传递的一个信息
     */
    console.log(data)  // ---->输出:成功后的数据
}).catch(err => {
    console.log(err)  // ---->输出:失败后的数据
})

代码分析:new Promise 中的异步任务的结果,无论是成功还是失败,下面都会获取到,并且你上面执行,我下面就可以同步获取到结果。

2.2.1 .then()嵌套

成功的情况:假如我还有异步任务呢?也就是说我第一个异步任务触发之后,还有异步任务怎么办?----> 直接在 then 中 return Promise 对象即可:

const p1 = new Promise((resolve, reject) => {
    resolve("任务1成功后的数据")
    // reject("任务1失败后的数据")
})
p1.then(data => {
    console.log(data)  
    return new Promise(((resolve, reject) => {
        resolve("任务2成功后的数据")
        // reject("任务2失败后的数据")
    }))
})
//这个.then就是处理上面then中return的Promise对象
.then(data1 => {
	console.log(data1)
})
.catch(err => {
	console.log(err)
})

所以这就避免了嵌套的层数,即使后面还有异步任务,也只需要套一层。

失败的情况:但是假如第一个 promise 失败了,由于任务是连续的,后面都会失败。然而这个 catch 只是第一个 then 的 catch,我想不同 then 有不同的 catch 怎么办?----> 跟成功一样,也 .catch ? 发现不行。所以:

每个 then 其实支持两个参数:第一个是函数(成功时触发),第二个也是函数(失败时触发)。如果第二个函数没有,就走 catch。所以就可以不用 catch,直接写第二个参数

const p1 = new Promise((resolve, reject) => {
    // resolve("任务1成功后的数据")
    reject("任务1失败后的数据")
})
p1.then(data => {
    console.log(data) 
    return new Promise(((resolve, reject) => {
        // resolve("任务2成功后的数据")
        reject("任务2失败后的数据")
    }))
}, err => {
    console.log("任务1失败了")
})
    .then(data => {
        console.log(data)
    }, err => {
        console.log("任务2失败了")
    })

为什么第二个错误输出为 undefined,也就是第二个错误没有触发?----> 在设置失败函数参数的时候,应该设置返回值,如果没设置,代表当前 then 是没有返回值的,就会默认返回一个成功 promise 对象,导致后面的 then 触发成功的函数参数。----> 所以需要设置返回值,方法:

  • 返回一个新的 promise,然后这个 promise 是一个失败的状态

  • 推荐:直接抛出异常:

    err => {
        console.log("任务1失败了")
        throw new Error('任务1失败了')
    }
    
2.2.2 fetch使用

这个 fetch 不是新内容,也是上面 promise 的一种用法,更多用于请求,其用法一样:

fetch('url').then(...)
            .then(...)

至此,关于 promise 的简单介绍和使用完毕!后续第二篇内容开始在 promise 的基础上介绍 async、await
附上链接:点击查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小学鸡!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值