zoukankan      html  css  js  c++  java
  • js中控制流管理的四种方法

    引自http://es6.ruanyifeng.com/#docs/generator#yield--表达式

    1.常用的回调方法

    step1(function (value1) {
      step2(value1, function(value2) {
        step3(value2, function(value3) {
          step4(value3, function(value4) {
            // Do something with value4
          });
        });
      });
    });

    2.ES6中的Promise

    Promise.resolve(step1)
      .then(step2)
      .then(step3)
      .then(step4)
      .then(function (value4) {
        // Do something with value4
      }, function (error) {
        // Handle any error from step1 through step4
      })
      .done();

    3.Generator同步的方法

    function* longRunningTask(value1) {
      try {
        var value2 = yield step1(value1);
        var value3 = yield step2(value2);
        var value4 = yield step3(value3);
        var value5 = yield step4(value4);
        // Do something with value4
      } catch (e) {
        // Handle any error from step1 through step4
      }
    
    scheduler(longRunningTask(initialValue));
    
    function scheduler(task) {
      var taskObj = task.next(task.value);
      // 如果Generator函数未结束,就继续调用
      if (!taskObj.done) {
        task.value = taskObj.value
        scheduler(task);
      }
    }

    另一种方法

    let steps = [step1Func, step2Func, step3Func];
    
    function *iterateSteps(steps){
      for (var i=0; i< steps.length; i++){
        var step = steps[i];
        yield step();
      }
    }

    4.Generator异步

    function run(fn) {
      var gen = fn();
    
      function next(err, data) {
        var result = gen.next(data);
        if (result.done) return;
        result.value(next);
      }
    
      next();
    }
    var g = function* (){
      var f1 = yield readFile('fileA');
      var f2 = yield readFile('fileB');
      // ...
      var fn = yield readFile('fileN');
    };
    
    run(g);
     

     5.async

    var asyncReadFile = async function () {
      var f1 = await readFile('/etc/fstab');
      var f2 = await readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };

    async函数对 Generator 函数的改进,体现在以下四点。

    (1)内置执行器。

    Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

    var result = asyncReadFile();
    

    上面的代码调用了asyncReadFile函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。

    (2)更好的语义。

    asyncawait,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

    (3)更广的适用性。

    co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。

    (4)返回值是 Promise。

    async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

    进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。

    demo:

    我们通过一个例子,来看 async 函数与 Promise、Generator 函数的比较。

    假定某个 DOM 元素上面,部署了一系列的动画,前一个动画结束,才能开始后一个。如果当中有一个动画出错,就不再往下执行,返回上一个成功执行的动画的返回值。

    首先是 Promise 的写法。

    function chainAnimationsPromise(elem, animations) {
    
      // 变量ret用来保存上一个动画的返回值
      var ret = null;
    
      // 新建一个空的Promise
      var p = Promise.resolve();
    
      // 使用then方法,添加所有动画
      for(var anim of animations) {
        p = p.then(function(val) {
          ret = val;
          return anim(elem);
        });
      }
    
      // 返回一个部署了错误捕捉机制的Promise
      return p.catch(function(e) {
        /* 忽略错误,继续执行 */
      }).then(function() {
        return ret;
      });
    
    }

    接着是 Generator 函数的写法。

    function chainAnimationsGenerator(elem, animations) {
    
      return spawn(function*() {
        var ret = null;
        try {
          for(var anim of animations) {
            ret = yield anim(elem);
          }
        } catch(e) {
          /* 忽略错误,继续执行 */
        }
        return ret;
      });
    
    }

    最后是 async 函数的写法。

    async function chainAnimationsAsync(elem, animations) {
      var ret = null;
      try {
        for(var anim of animations) {
          ret = await anim(elem);
        }
      } catch(e) {
        /* 忽略错误,继续执行 */
      }
      return ret;
    }
  • 相关阅读:
    DataSet中的数据全部插入数据库
    SQL养成一个好习惯是一笔财富
    C#不管什么四舍五入,只要是小数取整就得加1
    XMLNode与XmlNodeList
    ASP.NET2.0中配置文件的加密与解密
    编写一个文件目录常用操作的类
    上传文件的方法
    使用javascript 实现.net 验证控件功能
    SQLSERVER如何获取一个数据库中的所有表的名称、一个表中所有字段的名称
    Android之开启内置闹钟与已安装的应用程序设置
  • 原文地址:https://www.cnblogs.com/myzy/p/7246380.html
Copyright © 2011-2022 走看看