【问题标题】:Meteor (Fibers) loop and callbackMeteor (Fibers) 循环和回调
【发布时间】:2013-03-15 22:53:00
【问题描述】:

流星纤维“同步”模式让我发疯。这是一个简单的代码示例:

var feedsData = feeds.fetch(); // [{_id: "1234"}, {_id: "6789", url: "http://...."}]
for(var i = 0, len = feedsData.length; i < len; i++) {
    var feed = feedsData[i];
    parser.parseURL(feed.url, function(err, out){
        console.log(feed._id, i); // outputs "6789" and "2" each times
    });
}

我不明白如何进行这项工作。循环结束后调用回调,但内部内部变量如 feed 应该被保留……而不是。

解析的 url 很好(第一个,然后是第二个),但是我无法更新我的数据,因为我在回调中没有好的 _id。

想要的输出将是:“1234”“0”和“6789”“1”,而不是“6789”“2”两次...... 你会如何在 Meteor / Fiber 代码中做到这一点?

【问题讨论】:

    标签: javascript meteor node-fibers


    【解决方案1】:

    好的,这是执行此操作的“纤维”方式:

    var Future = require('fibers/future'),
    wait = Future.wait,
    feedsData = feeds.fetch(); // [{_id: "1234"}, {_id: "6789", url: "http://...."}],
    parseUrl = Future.wrap(parser.parseURL);
    Fiber(function() {
        for(var i = 0, len = feedsData.length; i < len; i++) {
            var feed = feedsData[i];
            var out = parseUrl(feed.url).wait();
            console.log('here', i, out);
        }
        console.log('there');
    }).run();
    console.log('and there');
    

    结果输出将是:

    "and there"
    "here" "0" "the out data from the 1st callback"
    "here" "1" "the out data from the 2nd callback"
    "there"
    

    正是您所期望的。 Fibers 中的“未来”期望给函数的最后一个参数是回调,并将返回 err 作为第一个参数

    【讨论】:

      【解决方案2】:

      最简单的解决方案是:

      feeds.fetch().forEach(function(feed,i) {
          parser.parseURL(feed.url, function(err, out){
              console.log(feed._id, i);
          });
      });
      

      Javascript 没有块作用域(不过,let 即将出现在 ES6 中),只有函数作用域。

      【讨论】:

        【解决方案3】:

        在“纤维”中的另一种方法(它可能比我上面发布的“未来”的答案更好):

        var feedsData = feeds.fetch(); // [{_id: "1234"}, {_id: "6789", url: "http://...."}]
        Fiber(function() {
            var fiber = Fiber.current;
            for(var i = 0, len = feedsData.length; i < len; i++) {
                var feed = feedsData[i];
                parser.parseURL(feed.url, function(err, out) {
                    console.log(feed._id, i);
                    if(err) return fiber.throwInto(err);
                    fiber.run();
                });
                Fiber.yield();
                console.log('here', i);
            }
            console.log('there');
        }).run();
        console.log('and there');
        

        输出将是:

        "and there"
        "1234" "0"
        "here" "0"
        "6789" "1"
        "here" "1"
        "there"
        

        请注意,Fiber 函数中的所有内容都在其自己的 Fiber 中执行,就好像它是异步的,这就是为什么首先输出“and there”的原因

        【讨论】:

          【解决方案4】:

          不确定这与 Meteor、Fibers 或“同步模式”有什么关系。我认为这只是您的javascript中的一个错误。您正在循环遍历数组,然后在回调中调用对象的属性。当然,最终调用回调时,它会查看feed 的当前值,这将是循环退出后最近分配的值。

          所以你应该重写你的代码以考虑到这一点:

          var feedsData = [{_id: "1234"}, {_id: "6789", url: "http://...."}]
          for(var i = 0, len = feedsData.length; i < len; i++) {
              var feed = feedsData[i];
              parser.parseURL(feed.url, function(err, out){
                  console.log(this._id, arguments[0]); // will output "1234 0" and "6789 1"
              }.bind(feed, i));
          }
          

          【讨论】:

          • 对不起,但这不起作用:TypeError:无法调用未定义的方法“绑定”。 feed 变量在每个循环内部,因此不应重新分配,在 2 个循环之后,每个回调都有两个独立的 feed 变量。我找到了我的问题的解决方案,我会在一分钟内发布它
          • 没有更多错误,但它仍然输出“6789”和“2”两次... :-/
          • 刚刚发布了 2 个不同的答案,两者都是有效的并且按“预期”工作:)
          • Javascript 没有块作用域,只有函数作用域。每次迭代都会重新分配您的 feed 变量。 Rahul 的回答是正确的 - 这与纤维、节点或流星无关,只是 Javascript :) bonsaiden.github.io/JavaScript-Garden#function.scopes
          猜你喜欢
          • 1970-01-01
          • 2013-11-28
          • 2017-04-29
          • 2015-03-06
          • 1970-01-01
          • 2018-06-26
          • 2017-02-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多