从生成器内部使用的迭代器回调中产生

Sea*_*ark 12 javascript function generator yield-keyword ecmascript-6

有没有人试图使用生成器来获得Underscore JS或lodash(或任何ES5标准函数)?

如果我们有一个数组var myArray = [1,2,3,4,6]; 我们希望每次都有它.

在非发电机的情况下,你会很简单

myArray.forEach(function(k) {
  console.log(k);
});
Run Code Online (Sandbox Code Playgroud)

但是,当你无法在非生成器函数内部产生时,所以如果在这个循环中我们必须做一些异步工作,你需要做以下事情.

var foreach = function* (arr, fn) {
  var i;
  for (i = 0; i < arr.length; i++) {
    yield * fn(arr[i], i);
  }
};

yield* foreach(myArray, function* (k) {
  var a = yield fs.readFile();
});
Run Code Online (Sandbox Code Playgroud)

哪种糟透了.

有人知道如何让匿名函数与生成器一起工作吗?因此,我们失去了整个lodash库.

注意:我正在使用Traceur将我的代码编译成ES6,并启用了生成器.
注意:我没有使用co().我正在使用下面看到的自定义生成器功能

var run = function(generatorFunction) {
  var generatorItr = generatorFunction(resume);
  function resume(callbackValue) {
    generatorItr.next(callbackValue);
  }
  generatorItr.next();
};
Run Code Online (Sandbox Code Playgroud)

mac*_*ost 1

如果我正确理解你的问题,那么本质上你正在尝试以异步方式做某事(迭代直到找到一个好的停止点),使用一种真正围绕同步性设计的语言(JS)。换句话说,虽然您通常可以这样做:

_([1,2,3]).any(function(x) {
    var shouldWeStopLooping = x % 2 == 0;
    return shouldWeStopLogging;
});
Run Code Online (Sandbox Code Playgroud)

相反,你想让“我们应该停止循环”代码从正常执行中中断,然后返回,这对于传统 JS 来说是不可能的(对于yield该语言来说相对较新),因此在 Underscore/Lodash 中也是不可能的:

_([1,2,3]).any(function(x) {
    var shouldWeStopLooping = $.ajax(...); // Doesn't work; code keeps going
    return shouldWeStopLogging;
});
Run Code Online (Sandbox Code Playgroud)

您可以采取两种方法,但都不是理想的方法。

正如评论中提到的,一种方法是首先完成所有“推迟”的工作,然后迭代:

var workInProgress = _([1,2,3]).map(someAjaxOperation);
$.when.apply(workInProgress).done(doSomethingBasedOnAjaxResults);
Run Code Online (Sandbox Code Playgroud)

但是(正如评论中所指出的)这并不完全相同,因为您最终对数组的所有元素进行 AJAX 工作(相对于真正的生成器,它只会迭代所需的数量来查找“赢家”)。

另一种方法是消除异步性。jQuery 允许您传递async: falseAJAX 请求,该请求通过让您使用 Underscore/Lodash/其他内容来“解决”问题...但它也会在执行 AJAX 工作时锁定用户的浏览器,这可能是不是你想要的。

不幸的是,如果你想使用像 Underscore/Lodash 这样的库,这些是我能看到的唯一选项。您唯一的其他选择是编写自己的 Underscore/Lodash mix-in,这实际上并不难。我建议这样做,因为它允许您仍然利用这些库中的所有其他出色功能,同时仍然以一致的方式进行迭代。