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

yielding from an iterator callback used inside a generator

本文关键字:迭代器 回调 内部      更新时间:2023-09-26

有没有人试图让Underscore JS或lodash(或任何ES5标准函数)与生成器一起工作?

如果我们有一个数组var myArray = [1,2,3,4,6];我们要对它进行forEach

在非生成器的情况下,您只需

myArray.forEach(function(k) {
  console.log(k);
});

然而,当你不能在非生成器函数中yield时,如果在这个循环中我们必须做一些异步工作,你需要做以下操作:

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();
});

哪一种烂。

有谁知道匿名函数与生成器一起工作的方法吗?因为这个,我们失去了整个lodash库。

注意:我正在使用Traceur将我的代码编译成ES6,并打开生成器。
注意:我没有使用co()。我使用如下所示的自定义生成器函数

var run = function(generatorFunction) {
  var generatorItr = generatorFunction(resume);
  function resume(callbackValue) {
    generatorItr.next(callbackValue);
  }
  generatorItr.next();
};

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

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

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

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

你可以采取两种方法,但这两种方法都不理想。

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

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

但是(正如在评论中所指出的),这并不完全相同,因为您最终对数组的所有元素执行AJAX工作(与真正的生成器相比,它只遍历所需的元素以找到"赢家")。

另一种方法是消除异步性。jQuery允许你传递async: false到一个AJAX请求,这"解决"的问题,让你使用下划线/Lodash/任何…但它也锁定了用户的浏览器,只要它需要做AJAX的工作,这可能不是你想要的。

不幸的是,如果你想使用像下划线/Lodash这样的库,这些是我能看到的唯一选项。您唯一的其他选择是编写自己的Underscore/Lodash混合,这实际上并不难。我建议这样做,因为它允许您在以一致的方式迭代的同时仍然利用这些库中的所有其他优秀函数。