微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript-具有功能的同步代码

以下功能允许使用睡眠功能创建无障碍的同步代码块.

function synchronous(generator)
{
   var _generator = generator();
   function done()
   {
      var result = _generator.next().value;
      if (result instanceof Promise)
         result.then(done);
   }
   done();
}

function sleep(ms)
{ 
   return new Promise(function(res, rej) { setTimeout(res, ms); });
}


// Runs without blocking, as you expect
synchronous(function* ()
{
   console.log('a');
   yield sleep(2000);
   console.log('b');
});

但是,以下代码将同时调用函数c()和d(),而不是在调用d()之前等待c()完成.

synchronous(function* ()
{
   Log('a');
   yield sleep(2000);
   Log('b');
   yield sleep(2000);

   synchronous(c);
   synchronous(d);

   function* c()
   {
      Log('c');
      yield sleep(2000);
      Log('d');
      yield sleep(2000);
   }

   function* d()
   {
      Log('e');
      yield sleep(2000);
      Log('f');
      yield sleep(2000);
   }
});

打印一个b c e d f

我该如何解决这个问题,并在c()完成之后使d()开始,而无需建立一个更为复杂的promise系统?

解决方法:

快速解决方

首先,您不能使异步函数同步.异步是有害的,这意味着所有调用异步代码并希望按顺序运行的代码本身都必须是异步的.在您的情况下,外部函数已经是异步的,因此您可以使用yield *使其工作:

synchronous(function* ()
{
   Log('a');
   yield sleep(2000);
   Log('b');
   yield sleep(2000);

   yield* c();
   yield* d();

   function* c()
   {
      Log('c');
      yield sleep(2000);
      Log('d');
      yield sleep(2000);
   }

   function* d()
   {
      Log('e');
      yield sleep(2000);
      Log('f');
      yield sleep(2000);
   }
});

好的解决方

您的同步函数可以由babelHelpers.asyncToGenerator代替:

function asyncToGenerator(fn) {
  return function () {
    var gen = fn.apply(this, arguments);
    return new Promise(function (resolve, reject) {
      function step(key, arg) {
        try {
          var info = gen[key](arg);
          var value = info.value;
        } catch (error) {
          reject(error);
          return;
        }
        if (info.done) {
          resolve(value);
        } else {
          Promise.resolve(value).then(function (value) {
            step("next", value);
          }, function (err) {
            step("throw", err);
          });
        }
      }
      step("next");
    });
  };
}

函数用于在定义时包装函数(而不是在调用时),如下所示:

var a = asyncToGenerator(function*() {
    yield sleep(100);
});
var b = asyncToGenerator(function*() {
    var c = asyncToGenerator(function*() {
        yield sleep(300);
    });
    var d = asyncToGenerator(function*() {
        yield sleep(300);
    });

    yield a();
    yield sleep(200);
    yield c();
    yield d();
});

b(); // start the whole process with b

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐