1

流星繊維の「同期」モードは私を夢中にさせています。簡単なコード例を次に示します。

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

これを機能させる方法がわかりません。ループが終了した後にコールバックが呼び出されますが、フィードなどの内部内部変数は保持する必要があります...そしてそれらは保持されません。

解析されたURLは適切です(最初のURL、次に2番目のURL)が、コールバックに適切な_idがないため、データを更新できません。

必要な出力は、「1234」「0」と「6789」「1」であり、どちらも「6789」「2」ではありません... Meteor /ファイバーコードでこれをどのように作成しますか?

4

4 に答える 4

1

「ファイバー」でそれを行う別の方法(そしてそれはおそらく私が上に投稿した「未来」の答えよりも良いでしょう):

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"

ファイバー関数のすべてが非同期であるかのように独自のファイバーで実行されることに注意してください。そのため、「andthere」が最初に出力されます。

于 2013-03-26T21:26:56.040 に答える
0

これが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));
}
于 2013-03-26T20:28:15.517 に答える
0

わかりました、これがそれを行う「ファイバー」の方法です:

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の「future」は、関数に指定された最後のパラメーターがコールバックであることを想定しており、最初のパラメーターとしてerrを返します。

于 2013-03-26T21:14:12.860 に答える
0

最も簡単な解決策は次のとおりです。

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

Javascriptにはブロックスコープがなく(まだletES6で提供されます)、関数スコープのみがあります。

于 2013-07-16T09:40:15.283 に答える