javascript 异步编程

为什么出现异步?js是单线程的执行,因为同步会堵塞。

异步的形式有哪些:回调函数、事件监听、Promise、Generator、async/await几种形式

异步和同步的区别

        同步执行的代码,加入某个js 执行的事件比较长,那么后边的代码都会等待执行,比方说ajax的同步请求,只有这个请求请求完成,其他的js才会执行。如果同步请求堵塞严重,就会造成造成页面请求后的js 没法执行,页面会出现空白等待区域。

       异步执行代码,恰恰和同步相反,执行代码到异步请求的时候,会把请求挂起,代码继续执行,等请求完成以后,再去执行异步代码请求的结果。

异步的解决方案

       异步的解决方案有:回调函数、事件监听、setTimeout/setInterval(定时请求)、Promise、Generator、async/await,

回调函数

       回调函数,是最初的解决方案,为了解决请求回来,继续调用写一个请求的时候使用

fs.readFile('a.txt',(err,data) =>{
    if(data) {
        fs.readFile('b.txt',(err,data) => {
            if(data){
                fs.readFile('c.txt',(err,data) => {
                    .....
                })
            }
        })
    }
})

这种方式算是js,最初解决异步的的方式,从而延申了回调地狱这个问题。

一般出现的情况会有

1、ajax求情回调

2、定时器回调

3、事件回调

4、node中的一些方法回调

回调地狱的缺点也显而易见,嵌套层级太多话,会出现无法维护与修改、代码量比较多。

Promise

     为了解决回调地狱,ES6的时候引入了promise的方式。这个promise算是解决了回调地狱的嵌套层级太多,带来的问题

function readFileFun(url) {
  return new Promise((resolve,reject) => {
    fs.readFile(url,function(err,data){
      if(err) reject(err)
      resolve(data) 
    })
})
}
readFileFun('a.txt').then(res=>{
    return readFileFun('b.text')
}).then(res=> {
  return readFileFun('c.txt')
}).catch(err => {
  console.log(err)
})

       这个代码就一目了然了,通过promise的来链式调用,解决了嵌套层级的问题,代码可读性提高了。别且用同步的形式把异步的操作表达了出来。promise还有是一些问题的。就是链式调用解决了嵌套层级多,没有从根本上解决,只是换了一种形式,代码可读性好了。promise也有一个all的方法来可以解决链式调用。

function readFileFun(url) {
  return new Promise((resolve,reject) => {
    fs.readFile(url,function(err,data){
      if(err) reject(err)
      resolve(data) 
    })
})
}

Promise.all([readFileFun('a.txt'),readFileFun('b.txt'),readFileFun('c.txt')]).then(data=> {
  console.log(data)
}).catch(err=> {
  console.log(err)
})

        这种形式看起来比链式调用好多了,代码看起来也比较清晰。代码可读性更高了。

Generator

       Generator也是一种异步解决的方案,最大的有点就是交出了函数的执行权,Generator可以看作是异步的执行器。暂停的时候通过yield来控制,Genetator函数配合yield来使用,别切返回的是一个迭代器,返回的形式一般都是[value:XXX,done:false]。当done为false的时候说明已经继续返回了。

function *gen() {
  console.log('开始')
  let a = yield 1
  let c = 4
  let b = yield (function(){return 2})()

  return 3
}
let gfun = gen()
console.log(gfun,'==========')  // Object [Generator] {} ==========
console.log(gfun.next())    // { value: 1, done: false }
console.log(gfun.next())    // { value: 2, done: false }
console.log(gfun.next())    // { value: 3, done: true } 

      没有使用yield的就没有出现打印 ,所以通过上边看得出,Generator的执行和返回。

async/await

       async/await是继ES6之后ES7推出的方案,它是Generator的语法糖,并且代码可读性非常高,同时也解决了promise链式调用的问题。

function testWait() {

    return new Promise((resolve,reject)=>{

        setTimeout(function(){

            console.log("testWait");

            resolve();

        }, 1000);

    })

}

async function testAwaitUse(){

    await testWait()

    console.log("hello");

    return 123;

    // 输出顺序:testWait,hello

    // 如果不使用await输出顺序:hello , testWait

}

console.log(testAwaitUse());

         执行上面的代码,从结果中可以看出,在正常的执行顺序下,testWait 这个函数由于使用的是 setTimeout 的定时器,回调会在一秒之后执行,但是由于执行到这里采用了 await 关键词,testAwaitUse 函数在执行的过程中需要等待 testWait 函数执行完成之后,再执行打印 hello 的操作。但是如果去掉 await ,打印结果的顺序就会变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值