promise & generator & async/await

本文深入探讨了回调地狱问题,分析其导致的代码可读性差、错误处理困难及控制反转的信任问题。通过对比Promise,阐述了其如何解决这些问题,包括提升代码可读性、简化错误捕获,并详细解析了Promise的状态转变、链式调用特性及其在解决控制反转问题上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// promise
// 关于回调地狱
/**
 * 回调函数带来的问题:
 * 1. 代码可读性差
 * 2. 回调比较多时,错误捕捉难处理 
 * 3. 控制反转带来的信任问题 -- 在进行异步请求时,用到第三方工具库,回调函数交由第三方库执行,
 * 由第三方库决定何时执行回调函数,执行回调函数次数,第三方工具库是否百分之百可靠,带来的信任问题
 */
// try {
    setTimeout(()=>{
        console.log(1)
        setTimeout(()=>{        
            try {
                console.log(2)
                throw new Error("error")
            } catch (error) {
                console.log(error)
                console.log("continue……")
            }        
            setTimeout(()=>{
                console.log(3)
                setTimeout(()=>{
                    console.log(4)
                },1000)
            },1000)
        },3000)
    },1000)       
// } catch (error) {
//     console.log(error)
//     console.log("continue……")
// }
/**
 * 回调地狱的错误捕获,只能在每个settimeout中进行try catch ,不能在整体外面使用try catch ,整体外面使用try catch ,try catch在主线程中进行,settimeout中抛出的任务在宏任务队列中,因此,整体外面添加try catch 不能捕获到settimeout中的错误
 */

 // Promise
 /**
  * Promise 解决了回调地狱的问题
  * Promise 三种状态 pending resolved rejected ,状态可以从pending转变为resolved或者rejected ,状态一旦改变后就不会再改变,通过then方法来实现链式调用
  * 缺点: 创建之后,立即执行,不能中途取消
  */

/**
 * 1. Promise then为promise状态改变的回调函数 通过then方法来实现链式调用
 */
new Promise((resolve)=>{
    setTimeout(()=>{
        console.log(1)
        resolve()
    },1000)
}).then(()=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(2)
            resolve()
        },1000)
    })
}).then(()=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(3)
            resolve()
        },1000)
    })
})    
// 1 2 3 

/**
 * 2. Promise中的错误捕获: Promise抛出的错误不会被外面的try catch捕获,会被catch捕获
 */
try {
    new Promise((resolve)=>{
        throw new Error("error")
        resolve()
    })
    .catch((reason)=>{
        console.log("catch error", reason) // 捕获
    })
} catch (error) {
    console.log("e", error) // 无法捕获
}
/**
 * Promise中的then中抛出的错误,也是不会被外部的try catch捕获,被.catch捕获,.catch相当于then的rejected状态回调函数的另一种写法
 * 捕获错误最好使用catch 
 * catch也会返回一个新的promise,后面还可以支持继续进行链式调用
 */
try {
    Promise.resolve().then(()=>{
        throw new Error("error")
    })
} catch (error) {
    console.log("e", error) // 捕获捕获
}
Promise.resolve(1)
.then(()=>{
    throw new Error("error")
})
.then(null, (reason)=>{
    console.log("reason", reason) // 捕获
})
.then(()=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            console.log("settimeout") // 执行
            resolve()
        })
    })
})
.catch((error)=>{
    console.log("catch", error) // 未捕获到错误
}).then(()=>{
    console.log("continue...") // 执行
})

/**
 * 3. promise解决回调地狱的控制反转的问题:
 * Promise 状态一旦改变之后不能再改变 -- 只能执行一次
 * Promise 状态一旦改变立即执行回调函数 -- 控制回调函数执行的时间
 */

// generator
/**
 * generator:
 * 状态机,函数分段执行
 * function 和 函数名之间 * ; yield执行停止的标志,next开始执行的命令
 * 根据next返回结果 可以查看函数是否执行完
 */
function * gene(){
    console.log(1)
    yield
    console.log(2)
    yield
    console.log(3)
    yield
}
var g = gene()
console.log(g.next()) // value: undefined done: false
console.log(g.next())
console.log(g.next())
console.log(g.next()) // done: true
console.log(g.next()) // done: true

function timer(time){
    return new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(time)
            resolve()
            run.next()
        }, time)
    })
}
// 异步
function *runner(){
    let p1 = yield timer(100)
    let p2 = yield timer(2000)
    let p3 = yield timer(300)
}
var run = runner()
run.next()
// 100 2000 300

// async/await
/**
 * async/await (generator语法糖)
 * async关键字放在函数function 之前, 声明函数为异步函数 ,函数返回Promise
 * await 只在异步函数中起作用,放在基于promise的函数之前,代码停在该处,直到promise执行完成状态改变才执行后面的函数
 * await 后面除了跟promise 还可以跟其他的任意表达式
 */
async function func(){
    await new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(1)
            resolve()
        }, 100)
    })
    await new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(2)
            resolve()
        }, 500)
    })
    await new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(3)
            resolve()
        }, 300)
    })
}
func().then(()=>{
    console.log("continue...")
})
// 1 2 3 continue...

/**
 * 判断执行顺序:
 * async函数中await之前的语句是同步执行的
 * await 后面的语句属于微任务队列
 */
async function async1(){
    console.log('async1 start');
     await async2();
     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

 async function func5(){
     console.log(1)
     await Promise.resolve(2)
     console.log(3)
 }
 func5()
 console.log(4)
 // 1 4 3

async function func4(){
    console.log(1)
    await setTimeout(()=>{
        console.log(2)
    },300)
    console.log(3)
}
func4()
setTimeout(()=>{
    console.log(5)
},500)
// 1 3 2 5

/**
 * ⚠️ await 后面的promise返回可能是reject 用try catch来捕获
 */
async function func2(){
    try {
        await Promise.reject(1)
    } catch (error) {
        return error
    }
}
func2()


内容概要:本文深入探讨了多种高级格兰杰因果检验方法,包括非线性格兰杰因果检验、分位数格兰杰因果检验、混频格兰杰因果检验以及频域因果检验。每种方法都有其独特之处,适用于不同类型的时间序列数据。非线性格兰杰因果检验分为非参数方法、双变量和多元检验,能够在不假设数据分布的情况下处理复杂的关系。分位数格兰杰因果检验则关注不同分位数下的因果关系,尤其适合经济数据的研究。混频格兰杰因果检验解决了不同频率数据之间的因果关系分析问题,而频域因果检验则专注于不同频率成分下的因果关系。文中还提供了具体的Python和R代码示例,帮助读者理解和应用这些方法。 适合人群:从事时间序列分析、经济学、金融学等领域研究的专业人士,尤其是对非线性因果关系感兴趣的学者和技术人员。 使用场景及目标:①研究复杂非线性时间序列数据中的因果关系;②分析不同分位数下的经济变量因果关系;③处理不同频率数据的因果关系;④识别特定频率成分下的因果关系。通过这些方法,研究人员可以获得更全面、细致的因果关系洞察。 阅读建议:由于涉及较多数学公式和编程代码,建议读者具备一定的统计学和编程基础,特别是对时间序列分析有一定了解。同时,建议结合具体案例进行实践操作,以便更好地掌握这些方法的实际应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值