16

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

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

在非发电机情况下,您只需

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

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

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

1 回答 1

0

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

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

相反,您想让“我们是否应该停止循环”代码从正常执行中中断,然后返回,这在传统 JS 中是不可能的(yield对于语言来说相对较新),因此在 Underscore/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 请求,该请求通过让您使用 Underscore/Lodash/whatever 来“解决”问题......但它也会锁定您用户的浏览器,只要它需要执行 AJAX 工作,这可能不是你想要的。

不幸的是,如果你想使用像 Underscore/Lodash 这样的库,我只能看到这些选项。您唯一的其他选择是编写自己的 Underscore/Lodash 混合,这真的不难。我建议这样做,因为它可以让您仍然利用这些库中的所有其他强大功能,同时仍然以一致的方式进行迭代。

于 2014-08-04T19:52:36.483 回答