「提问」看了下 babel 转译的 async/await,执行了一个 while(true) {},为啥不会卡住……

2016-12-16 17:41:16 +08:00
 2zH

最近对async/await的实现产生了兴趣,看了下babel的转译,调用了regeneratorRuntime的几个函数。

打开源码看了一下午,有很多东西不是很理解。

while (1) {
    switch (_context.prev = _context.next) {
      case 0:
        _context.next = 2;
        return setTimeout(function (v) {
          return console.log(v);
        }, 1000);

      case 2:
      case "end":
        return _context.stop();
    }
}

以上代码我目前的理解是执行了个状态监听器,await后的函数执行完毕后会改变_context.next,然后结束这个状态机。

但在 console 中,执行while(true){}页面几乎是秒卡的。

求指教!

以上运行环境为 chrome console 。

async function log (v) {
  await setTimeout(v => console.log(v), 1000)
}

babel =>

"use strict";

var log = function () {
  var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(v) {
    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return setTimeout(function (v) {
              return console.log(v);
            }, 1000);

          case 2:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, this);
  }));

  return function log(_x) {
    return _ref.apply(this, arguments);
  };
}();

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 { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
5420 次点击
所在节点    Node.js
3 条回复
lujjjh
2016-12-16 21:24:49 +08:00
因为有 return ,所以循环只会跑一次……而且 setTimeout() 返回的并不是一个 Promise ,用 await 怪怪的吧。

while (1) 其实是给 loop 里有 await 的用的,比如 for (let i = 10; i--; ) await Promise.resolve();

如果可以直接 goto 到某个 label 的话,就不需要这个 while (1) 了。
lujjjh
2016-12-16 21:34:29 +08:00
我也没研究过 Babel transpile 出来的代码,好像只要 await 在控制流程语句或者 try...catch block 里就没法在 switch 里一路 fallthrough 下去,需要跳转到隔开的某个状态里。
2zH
2016-12-19 15:27:02 +08:00
@lujjjh
async 内部 return 的好像就是一个 promise:

function _asyncToGenerator(fn) {
return function() {
var gen = fn.apply(this, arguments);
return new Promise(function(resolve, reject) {...
});
};
}

var log = function () {
var _ref = _asyncToGenerator(...);

return function log(_x) {
return _ref.apply(this, arguments);
};
}();

之前没有注意到 while 里面那个 return ,下一步往哪里挖有了许多头绪,谢谢指教!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/328145

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX