ES6-promise—使异步函数顺序执行。(同时防止回调地狱的问题)

什么是:专门保证多个异步函数,可以顺序执行的机制。而且防止了回调地狱的问题。

ES6 promise
第一步:异步函数的内部,用 new Promise(function(door){…})包裹原函数中所有的代码。
第二步:在异步任务执行完最后一步后,调用附赠的开关door()开门,通知下一项任务可以执行;
第三步:将整个new Promise()对象返回到函数内部,再使用.then()接下一项任务函数。

function fn1(){
    return new Promise(
      function(door){
        var demo="唯一的一个接力棒";
        console.log(`1号拿着${demo}起跑。。。`);
        setTimeout(function(){
          console.log(`1号拿着${demo}到达终点`);
          console.log(`1号打开了门(door),把${demo}交给了下一位`);
          door(demo);
        }, 3000);
      }
    )
  }

  function fn2(demo){
    return new Promise(
      function(door){
        console.log(`2号拿着${demo}起跑。。。`);
        setTimeout(() => {
          console.log(`2号到达了终点`);
          console.log(`2号打开了门,把${demo}交给了下一位`);
          door(demo);
        }, 2000); 
      }
    )
  }

  function fn3(demo){
    return new Promise(
      function(door){
        console.log(`3号拿着${demo}起跑`);
        setTimeout(() => {
          console.log(`3号到达终点`);
          console.log(`3号打开了门`);
          door();
        }, 5000);
      }
    )
  }

执行

fn1().then(fn2).then(fn3).then(()=>console.log("比赛结束了"))

当前一个函数内调用door()后,就等于通知了.then()中的下一个函数可以开始执行。于是.then()就自动执行下一个函数。
注意:
1 then()中的下一个异步函数后不要加(),因外下一个异步函数不是立即调用,而是等前一个函数开门。
2 .then()能否接下一个.then(),取决于前一个.then()中的函数是否也支持promise。如果前一个.then()中的函数支持promise,则.then()可以继续.then()。否则不能继续.then().(???)

如何实现前后两个函数之间的传参:
(1)上一个函数中有door;
(2)下一个函数(最外层函数)定义时就要定义一个形参用来接。
原理:参数值会顺着.then()交给.then()中的下一个函数的形参变量。下一个就可以通过自己的形参变量获取到上一步传过来的参数值。
局限:door()只能传递一个变量。如果传递多个值,可以将多个值放在数组或者对象中整体传入。

错误处理
当异步执行任务发生错误,就可以从报错的门(.catch())出去。且一旦从报错这扇门出去,后续的.then()都不再执行。

  function fn1(){
    return new Promise(
      function(door,err){
        var demo="唯一的一个接力棒";
        console.log(`1号拿着${demo}起跑。。。`);
        setTimeout(function(){
        if(Math.random()>0.5){
            console.log(`1号拿着${demo}到达终点`);
            console.log(`1号打开了门(door),把${demo}交给了下一位`);
            door(demo); 
        }else{
          console.log(`1号摔倒了`);
          err("1号摔倒了");
        }
        }, 3000);
      }
    )
  }

  function fn2(demo){
    return new Promise(
      function(door,err){
        console.log(`2号拿着${demo}起跑。。。`);
        setTimeout(() => {
          if (Math.random()<=0.5){
            console.log(`2号到达了终点`);
            console.log(`2号打开了门,把${demo}交给了下一位`);
            door(demo);
          }else{
            console.log(`2号摔倒了`);
            err("2号摔倒了");
          }
        }, 2000); 
      }
    )
  }

  function fn3(demo){
    return new Promise(
      function(door,err){
        console.log(`3号拿着${demo}起跑`);
        setTimeout(() => {
          if (Math.random()>0.5){
            console.log(`3号到达终点`);
          console.log(`3号打开了门`);
          door();
          }else{
            console.log("3号摔倒了");
            err("3号摔倒了")
          }
        }, 5000);
      }
    )
  }

//调用: 
fn1().then(fn2).then(fn3).then(()=>console.log("比赛结束了"))
.catch(function(err){
  console.log(err);
  console.log("弃权!")
})

**.catch()**方法用来捕捉按顺序执行的出错的异步程序,其中某一步出错,后面的异步程序都不再执行。

promise的问题:没有彻底消除嵌套。
当多个异步函数需要顺序执行时:
(async function(){
同步代码;
var 返回值=await 异步函数;
同步代码;
} )()

具体代码如下:

(async function(){
  try{
    var bang=await fn1();
    bang=await fn2(bang);
    await fn3(bang);
    console.log("比赛结束");
  }catch(err){
    console.log(err);
    console.log("有人摔倒,比赛结束");
  }
})();

promise深入理解

await: 让整段匿名函数自调暂时挂起,等待当前异步函数执行结束,再执行后续代码
注意:
1 ES7的async和await仅仅简化的是promise函数调用的部分。并没有简化promise函数的定义。且如果想用await,则异步函数必须定义为支持promise的样式;
2 如果await修饰的异步函数中调用了err()方法,打开了错误的门,则await会认为程序错误。此时应该使用try{}catch(err){} 解决;
3 只有async下的try catch 才能捕获异步任务中的错误。没在async下的js基础所学的try catch 是无法捕捉异步任务的。因为js基础中的try catch 属于主程序,不会等到异步任务执行,就已经结束了。即使异步任务出错,try catch因为早就结束了,所以无法捕获到。
4 为何await 配合try catch就可以捕获异步任务中的错误?
答:因为await能留住当前程序中的一切代码,等待异步函数执行结束。try catch就有可能捕获到异步任务中的错误。

你可能感兴趣的:(JavaScript,js,es6)