嵌套的promise执行顺序以及多个promise顺序执行

1. promise.resolve()

① 不带参数的时候,直接返回一个resolved状态的promise对象

promiseStatus:resolved

promiseValued : undefined

② 带参数时 参数会传给回调函数

promiseStatus:resolved

promiseValued : 参数

2. 每次调用then都会返回一个新创建的promise对象

情况①若then方法中含有return语句,且返回的是一promise对象,则该对象作为then返回的新对象;

情况②若返回的是一个非promise对象,则返回的新promise对象的promiseValue为该值;

情况③若无返回值则返回的新promise对象promiseValue为undefined。

let newPromise = Promise.resolve().then(res =>{
    // 无返回值
})
let newPromise2 = Promise.resolve().then(() => {
    // 返回一个非promise对象
    return "hello" 
})
let newPromise3 = Promise.resolve().then(() => {
     // 返回promise对象
    return new Promise((resolve, reject) => {
        resolve("bonjour")
    })
})
console.log(newPromise, newPromise2, newPromise3)

3. 只有返回promsie对象后才会链式调用

Promise.resolve().then(res => { //then1
   console.log('1')
   new Promise((resolve, reject) => { 
        setTimeout(() => {
            console.log('2')
            resolve('newPromise')
        }, 2000);
    }).then(res =>{ // then2
        console.log('3')
        return "newPromise1"
        // 返回了一个非promsie对象,对应2中的情况2
    })
    // 无return语句,对应2中的情况3 
}).then(res=>{ // then3
    console.log('4', res)
})

输出结果是:1 4 undefined 2 3

执行then1, 输出1,执行同步任务new promise实例,遇到异步任务挂起,继续向下执行,then1中无return语句,则对应2中的情况①,返回一个值为undefined的promise对象,链式调用then3,输出 4 undefined ,2s后输出2,调用then方法输出3,且又创建了一个值为newPromise1的promise对象。

Promise.resolve().then(res => { //then1
   console.log('1')
    // then1中返回一个新的promise实例 只有当then1中返回的promise状态确定后才会进行下一步的链式调用 then3
   return new Promise((resolve, reject) => { 
        setTimeout(() => {
            console.log('2')
            resolve('newPromise')
        }, 2000);
    }).then(res =>{ // then2
        console.log('3')
        return "newPromise1"
    })
   // 有return语句,且返回了一个promise对象,对象2中的情况1
}).then(res=>{ // then3
    console.log('4', res)
})

输出结果: 1 2 3 4 newPromise1

因为then1中含有return语句,且返回了一个promise对象,代码中先new一个promise实例,且由于每次调用then都会创建一个新的promise实例,所以只有当执行完 return "newPromsie1"后,then1返回一个值为newPromise1的promise对象,才会继续链式调用then3。

可以利用这种特性去实现顺序执行多个异步任务

4. 顺序执行多个异步任务

第一种思路是利用then链式调用的特点实现

1.直接then链式调用。
2.利用Promise.resolve()+forEach循环/reduce循环,将promise串成一任务队列,本质上是简化的链式调用。

三个模拟的异步任务

let a = function() {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('11111111111',)
            resolve('第一个异步进程')
        },3000)
    })
} 
let b = function(){
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('2222222222' )
            resolve('第二个异步进程')
        },2000)
    })
}
let c = function(){
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('3333333333333')
            resolve('第三个异步进程')
        },1000)
    })
}

reduce构建异步队列

let promiseArr = [a, b, c]
promiseArr.reduce((prev, cur)=>{
    return prev.then(() => {
            return cur().then(res => {
                console.log( res)
            })
    })
}, Promise.resolve())

本质上相当于

Promise.resolve().then(res => {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('11111111111', )
            resolve('第一个异步进程')
        },3000)
    })
    // 只有当第一个then返回了promise对象才会接着调用下一个的then方法
}).then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('2222222222', )
            resolve('第二个异步进程')
        },2000)
    })
}).then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(()=>{
            console.log('33333333', )
            resolve('第三个异步进程')
        },1000)
    })
})

forEach构建异步队列

function fun(arr){
    let res = Promise.resolve()
    arr.forEach(item => {
        res = res.then(item)
    })
}
fun([a,b,c]).then( res => {
    console.log(res)
})

//相当于
Promise.resolve().then(
    a
).then(
    b
).then(
    c
)
3. async await实现
let arr = [a, b, c]
async function fun(arr){
    for(const item of arr){
        const res = await item().then()
        console.log(res)
    }
}
fun(arr)
### JavaScript Promise 执行顺序解析 在 JavaScript 中,`Promise` 是一种处理异步操作的方式。当 `Promise` 创建时,它会立即执行传入的执行器函数,并进入 pending 状态。根据内部逻辑的不同,它可以转换到 fulfilled 或 rejected 状态。 #### 初始状态与回调注册 一旦创建了一个 `Promise` 对象,在其构造函数内指定的执行器函数会被立刻调用[^5]: ```javascript const myPromise = new Promise((resolve, reject) => { // 此处代码会在myPromise实例化的同时被执行 }); ``` 此时如果通过 `.then()` 方法为该 `Promise` 注册成功和失败后的回调函数,则这些回调并不会马上被触发,而是要等到当前同步任务全部完成后才会按序依次处理微任务队列里的待办事项——即所谓的“事件循环”。 #### 成功路径下的行为模式 假设一切顺利,那么执行器内的某个条件满足后将会调用 `resolve(value)` 来结束这个过程并将结果传递出去;与此同时任何预先设定好的`.then(onFulfilled[, onRejected])` 将按照它们被附加上的先后次序逐一响应此变化: ```javascript myPromise.then( value => console.log(`Resolved with ${value}`), error => console.error(error.message) ); // 如果前面已经有一个成功的resolve(),这里就会打印出对应的value ``` 值得注意的是每次调用 `.then()` 不仅能接收前一次的结果作为输入参数,而且还会返回一个新的 `Promise` 实例以便继续链式调用更多后续动作[^2]: ```javascript new Promise(resolve => setTimeout(() => resolve(10), 100)) .then(num => num * 2) .then(doubledNum => doubledNum + " is the final result.") .then(console.log); // 输出:"20 is the final result." ``` #### 失败情况下的传播机制 相反地,假如过程中出现了异常情形导致需要提前终止整个链条的话,就可以利用 `reject(reason)` 把控制权交给最近一层带有错误处理器的那个节点去接管并作出适当反应。未被捕获的 rejection 默认情况下会使程序抛出全局性的 UnhandledRejection 错误警告。 ```javascript let failedPromise = new Promise((_, reject) => { throw new Error("Something went wrong!"); }); failedPromise.catch(err => alert(err)); // 显示弹窗提示:“Something went wrong!” ``` 另外需要注意一点就是即使存在多层嵌套结构下只要任意一处发生拒收现象都会直接跳过中间环节直达最外层的第一个可用 catch 块为止[^4]。 #### 并发竞争场景分析 对于并发条件下多个异步任务之间的竞态关系(race condition),可以通过内置工具函数如 `Promise.race(iterable)` 和 `Promise.all(iterable)` 来简化管理复杂度。前者允许监听最先改变状态的任务而后者则需等待所有成员都达成一致才给出反馈[^1]。 例如下面的例子展示了如何让两个不同耗时长度的操作相互竞赛看谁先完成: ```javascript function requestImg(url){ return fetch(url).then(response=>response.blob()); } function timeout(ms){ return new Promise((resolve,reject)=> setTimeout(()=>resolve('timed out'), ms) ); } Promise.race([requestImg('/path/to/image.jpg'), timeout(5000)]) .then(result => console.log(result)) // 展示较快者的结果 .catch(e => console.warn(e)); // 捕捉可能出现的问题 ``` 在这个案例里无论是网络请求还是定时器哪一个更快达到终点都将决定最终输出什么内容给用户看到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值