5

私はnodejsが初めてで、おそらくイベントシステムがどのように機能するかわかりません。バグが見つかりません。ご意見をお聞かせください。簡単なタスクが必要です。タグを確認し、存在しない場合は、新しいキーとタグに関する情報を設定します。問題は、スクリプトを初めて実行すると、常に「キーが存在しません」が返されることです。redisdbキーを確認してください-多くのタグが作成されますこれが私のコードです

for (x = 0; x < rows.length; x++) {
    if (rows[x].term_taxonomy_id != 1) {
        var taxonomy = findOne(rterms, rows[x].term_taxonomy_id);
        rc.exists('tag:' + taxonomy.name, function (err, rexists) {
            if (rexists == false) {
                rc.incr('tags:count', function (err, id) {
                    console.log(taxonomy.name+' not exists. result ' + rexists);
                    rc.set('tag:' + taxonomy.name,id);
                    rc.hmset('tag:' + id,
                        'id', id,
                        'title',taxonomy.name,
                        'url', taxonomy.slug
                    );
                });//incr
            }else{
                console.log(taxonomy.name+' exists!'+rexists);
            };
        });//exists
    };//ifrows
});

ここに別の一例があります

var tags = [
  "apple",
  "tiger",
  "mouse",
  "apple",
  "apple",
  "apple",
  "tiger",
  "mouse",
  "mouse",
];
var count =0;
Object.keys(tags).forEach (function (tag) {
  rc.get("tag:"+tags[tag],function(err,rr){
    console.log("get tag "+tags[tag]+" result code "+rr);
    if (rr == null) {
      rc.set("tag:"+tags[tag],"info",function(err,rr){
        count++;
        console.log('set tag '+tags[tag]+' '+rr+' objects count '+count);
      });
    };
  });
})

出力:

get tag apple result code null
get tag tiger result code null
get tag mouse result code null
get tag apple result code null
get tag apple result code null
get tag apple result code null
get tag tiger result code null
get tag mouse result code null
get tag mouse result code null
set tag apple OK objects count 1
set tag tiger OK objects count 2
set tag mouse OK objects count 3
set tag apple OK objects count 4
set tag apple OK objects count 5
set tag apple OK objects count 6
set tag tiger OK objects count 7
set tag mouse OK objects count 8
set tag mouse OK objects count 9

nodejs はすべての「get」コマンドを実行し、その「set」コマンドの後にのみ実行するようです。だから...私は理解しています、それはすべて非同期操作のためです。しかし、それを機能させる方法は?

4

1 に答える 1

5

このコードには少なくとも 2 つの問題があります。

  • 最初のものは Javascript クロージャ管理にリンクされています。ループの本体はスコープを作成しません。Javascript では、変数のスコープはブロック レベルではなく関数レベルにあります。適切なクロージャーの作成を強制するには、ループ自体に何らかの関数を導入する必要があります。詳細はこちら

  • 2 つ目は、exist コマンドと set コマンドの間の競合状態です。複数の Redis 接続が存在し、同じキーでコマンドを設定している場合、何らかの競合が発生する可能性があります。exists と set を使用する代わりに、1 つのアトミック操作でチェックと設定を実行するsetnxを使用する必要があります。

2 番目の例を考えると、クロージャの問題は forEach を使用して修正されましたが、言語の非同期性のために、set 操作の前にすべての get 操作を生成します。

すべての get 操作と set 操作を順番に並べる必要がある場合 (かなり遅くなります)、関数型プログラミングを少し使用して、再帰を使用してループを実装できます。

このプログラム:

var redis = require('redis')
var rc = redis.createClient(6379, 'localhost');

var tags = [
  "apple",
  "tiger",
  "mouse",
  "apple",
  "apple",
  "apple",
  "tiger",
  "mouse",
  "mouse",
];

var count = 0;

function loop(tags) {
  function rec_loop(tags,i) {
     if ( i >= tags.length )
        return
     rc.get("tag:"+tags[i],function(err,rr) {
        console.log("get tag "+tags[i]+" result code "+rr);
        if ( rr == null ) {
           rc.set("tag:"+tags[i],"info",function(err,rr) {
              count++;
              console.log('set tag '+tags[i]+' '+rr+' objects count '+count);
              rec_loop(tags,++i)
           })
        } else
          rec_loop(tags,++i)
     })
  }
  rec_loop(tags,0)
}

loop(tags)

表示:

get tag apple result code null
set tag apple OK objects count 1
get tag tiger result code null
set tag tiger OK objects count 2
get tag mouse result code null
set tag mouse OK objects count 3
get tag apple result code info
get tag apple result code info
get tag apple result code info
get tag tiger result code info
get tag mouse result code info
get tag mouse result code info

この例では競合状態がまだ存在することに注意してください。この種のチェックおよび設定操作を実装するには、setnx を使用することになっています。

于 2012-06-12T17:27:42.227 に答える