分享

异步函数与同步函数

 python_lover 2022-11-30 发布于北京

一、异步函数与同步函数的操作顺序

例子1:异步爸爸和异步儿子、同步儿子的故事

async function myAsync(){
  timer= await setInterval(()=>{
  console.log(count)
  count++;
  if(count>10){clearInterval(timer)}
    console.log("我是异步")
  },100)
  console.log("我是同步")
}
myAsync()

 

 

 if和console.log()是属于同一级别的,但是因为if里面有异步函数,所以比同步慢执行;

例子2:异步爸爸和异步儿子,与同步兄弟的故事

async function myAsync(){
  timer= await setInterval(()=>{
  console.log(count)
  count++;
  if(count>10){clearInterval(timer)}
    console.log("我是异步")
  },100)
  console.log("我是同步1")
}
myAsync()
console.log("我是同步2")

 

 

 console.log("同步2")与myAsync是同一级,但是myAsync是异步函数,所以先输出同步2,又因为例子1说明的原因,所以再输出同步1,最后执行我是异步。

例子3:同步爸爸与异步儿子,与同步兄弟的故事

function myAsync(){
  timer= setInterval(()=>{
  console.log(count)
  count++;
  if(count>10){clearInterval(timer)}
    console.log("我是异步")
  },100)
  console.log("我是同步1")
}
myAsync()
console.log("我是同步2")

 

 

 此时由于myAsync与console.log()都是同一级别的,所以遵循从上到下执行,又因为myAsync的儿子是异步,所以myAsync的儿子最慢执行。

例子4:

async function myAsync1(){
  timer= setInterval(()=>{
  console.log(count)
  count++;
  if(count>10){clearInterval(timer)}
    console.log("我是异步1")
  },100)
}
async function myAsync2(){
  setTimeout(()=>{
    console.log("我是异步2")
  },100)
}
myAsync1()
myAsync2()
console.log("我是同步2")

同样,同步最先执行,两个异步都是同级,按时间触发顺序,执行

 

 把例子4的两个异步调一下个:

async function myAsync1(){
  timer= setInterval(()=>{
  console.log(count)
  count++;
  if(count>10){clearInterval(timer)}
    console.log("我是异步1")
  },100)
}
async function myAsync2(){
  setTimeout(()=>{
    console.log("我是异步2")
  },100)
}
myAsync2()
myAsync1()

console.log("我是同步2")

 

 根据上面几个例子说明:

(1)同一级别下,同步异步执行顺序都是同步函数最先执行,异步函数最慢执行

(2)而两个一样的异步函数,按照顺序,上面的先执行,下面的慢执行

(3)两个不一样的异步函数,要比较异步函数内部是否有继续嵌套异步,还是嵌套同步,有同步的先执行;

(4)两个一样的异步执行函数,但是时间触发不一样的,按照时间触发先后,按顺序执行,这也就是实际开发中,你并不知道你向服务器索取的资源哪一个先拿到。先拿到资源的,就先执行,但是这个时间是未知的。

------------------------------------------------------------------------------------------------------------------------------------------开始讲些有用的:

写个例子:

let arr1 = []
function myAsync(){
  setTimeout(()=>{
   return arr1.push(1);//对数组赋值
  },1000)
}
let num = myAsync();
console.log(num);

运行结果:

 

 答案很明显,赋值时由于异步函数setIterval还没操作,就赋值了,明显赋了个寂寞,所以undefined;

那么早期的时候,我们是怎么拿到异步函数里面的值的呢?

 

二、早期与异步函数的爱恨情仇:

利用回调函数!看下面这个例子:

let arr1 = []
function myAsync(callback){
  setTimeout(()=>{
   return callback(arr1.push(1));//对数组赋值
  },1000)
}

传入一个参数callback,这个参数其实就是一个函数,那么怎么取值?

// 箭头函数写法
myAsync((arg)=>{
  console.log(arg);//arg为参数,其实就是拿到了arr1.push里面的内容
})
//es5写法
myAsync(function callback(arg){
console.log(arg)
})

 

 执行顺序分析:首先执行myAsync(),执行完毕后回调callback(),开始执行,这就是所说的回调函数,说白了就是先执行myAsync(),接着执行callback,如何callback内部把内容输出。所以拿到值的其实是callback帮忙拿到的。

 

有了上面这个思路,所以我们的前辈们很开心,找到了探索新世界的大门,用之而来请求网络数据时非常开心,因为可以拿到异步操作里面的值了!

 

 

然而开心了没多久,开始难过了,此时出现了一个怪物:

 

 他叫回调地狱,为什么会有它呢,其实实际应用场景需要先完成第一个异步任务,才能执行第二个异步任务,接着才能完成第三个异步任务,具体例子我现在还没想到,知道的可以评论一下,因为我是个菜鸡。

接着你看一下下面这个例子:

async function myAsync1(callback){
  setTimeout(()=>{
    callback(arr1.push("任务1,我需要最先完成"))
  },1000)
}

async function myAsync2(callback){
  setTimeout(()=>{
    callback(arr1.push("任务2,我需要第二完成"))
  },1000)
}

async function myAsync3(callback){
  setTimeout(()=>{
    callback(arr1.push("任务3,我需要最慢完成"))
  },1000)
}

function totalTasks(){
  myAsync1(cb1=>{
    // 若cb1非空,就是cb1初始化了,可以操作cb1了,专业点说法就是它加载入内存了,,才能继续下面执行cb2,,下面依次类推
    if(cb1){
      console.log(arr1)
      myAsync2(cb2=>{
        if(cb2){
          console.log(arr1)
          myAsync3(cb3=>{
            if(cb3){
              console.log(arr1);
            }
          })
        }
      })
    }
  })
}
totalTasks()

结果:

 

 这还是仅仅三层回调,那么要是多层回调,再写成网络请求格式的,你会写到一半自己线绕晕了。

所以前辈们写这个的时候表情是这样子的:

 

 想拉屎,但是又拉不出来的感觉。

三、promise救世主的出现

 

 愚笨而又可爱的人类啊,我来拯救你们啦:

此时我们只要这样写就好了:

async function myAsync(){
 return await new Promise(res=>{
    setTimeout(()=>{
      arr1.push(1)
      res(arr1)
    },100)
    
 })
}
let p = myAsync()
p.then((data)=>{
console.log(data)
})

promise呢,其实也是用的回调的思想,但是他这种语法格式我们用起来理解就简单多了,维护起来也方便。

它执行的原理就是回调,他其实有两个参数,第一个参数是resolve,表示成功取到值的操作,第二个,表示请求被拒绝的操作,这两个参数也都是回调函数。

下面看个例子,讲一下里面的各个参数的作用:

new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功') // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)

resolve(参数),如果数据请求成功,它会把参数发给then,以备进行下一步操作,reject(参数),如果数据请求错误,他会把参数传给then以备下一步操作。

而then函数它其实也是一个promise函数,它的两个参数作用也一样,then函数可以传给下一个then函数,子子孙孙无穷尽也。

形如:

new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功') // 数据处理完成
    reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)

其实还有一个catch函数,它的作用相当于then函数的第二个参数,也相当于promise的第二个参数,都是用来处理错误操作的:

new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功') // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
).catch{

console.log(err)    
}

具体为什么多次一举,加个catch,因为前面的then函数已经可以处理错误操作了,网上说还是可能异步引起的错误,有些错误只有catch才能发现,这个等我变成大神后再说下原因。

四、promise,与async 与await实现异步操作按顺序执行:

// 2.await async 与promise
async function myAsync1(){
  return await new Promise(res=>{
     setTimeout(()=>{
       console.log("任务1")
       res("任务1")
     },1000)
     
  })
 }

 async function myAsync2(){
  return await new Promise(res=>{
     setTimeout(()=>{
      console.log("任务2")
      res("任务2")
     },10)
     
  })
 }

 
 async function myAsync3(){
  return await new Promise(res=>{
     setTimeout(()=>{
      console.log("任务3")
      res("任务3")
     },1)
     
  })
 }
 async function totalTask(){
   await myAsync1();
   await myAsync2();
   await myAsync3();
 }
 totalTask()

 

 直接用async 与await实现异步函数顺序执行。

注:async与await关系密切,只有声明了async的函数,里面才能使用await。await作用就是等待这个函数执行,等待执行完再执行下一个。

 

好了,写到这里了,我好帅啊!

 

 

async function myAsync1(){
  timersetInterval(()=>{
  console.log(count)
  count++;
  if(count>10){clearInterval(timer)}
    console.log("我是异步1")
  },100)
}
async function myAsync2(){
  setTimeout(()=>{
    console.log("我是异步2")
  },100)
}
myAsync1()
myAsync2()
console.log("我是同步2")

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多