0

setTimeout特に並列呼び出しの場合に競合状態を解消するために、javascript の各スタックに一種の「プライベート レルム」または「プライベート メモリ」を使用する方法があるかどうかを知りたいです。

たとえば、私がこれを持っているとしましょう:

function foo() { 
    /* some statements */ 
    bar(); 
} 

function bar() { throw new Exception("oooh damn!"); }

setTimeout(function() { foo(); }, 10);
setTimeout(function() { foo(); }, 10);

2 つの例外が発生する予定ですが、どの呼び出しに対応するのかわかりません。

一種のプライベート レルムを実装することもできますが、コードが非常に複雑になるため、ネイティブ ソリューションがあればそれを使用したいと考えています。

4

6 に答える 6

1

setTimeout関数を変更して、すべての回答の経験を集計できます。

var oldTimeout = window.setTimeout;
window.setTimeout = function(callback, delay){
    if(callback.name == 'Trace'){
        oldTimeout.apply(this,[function(){
            try{
                callback.apply(this,arguments);
            }
            catch(e){                
                e.message += ' ('+e.stack.split('\n').map(function(e){return '['+e.replace(location.href,'plain_script').replace('@',' in ')+']'}).join(' < ')+')';
                throw e;
            }
        }].concat(Array.prototype.slice.call(arguments,1,arguments.length)));
    }
    else{oldTimeout.apply(this,arguments)};
}

http://jsfiddle.net/RSbtF/1/

于 2013-05-01T19:29:51.863 に答える
1

おそらく、クロージャーを少し違った方法で使用し、グローバル変数を避けるでしょう。ID を、呼び出しのカウントや競合状態の処理を可能にするコンテキスト オブジェクトに置き換えることができます。

var invokeWithId = function(id, f){
    return function(){               
        f.apply({id:id}, arguments);
    }
}
setTimeout(invokeWithId(1, foo), 10);

http://jsfiddle.net/j8hgE/

于 2013-04-30T18:09:03.283 に答える
1

foo()追跡するために、何らかの識別子をに渡すことができます。これを試して:

setTimeout(function () { foo(1); }, 10);
setTimeout(function () { foo(2); }, 10);

そしてfoo()、id 引数を受け入れて渡すように関数を変更します。

function foo(id) {
    /* some statements */
    bar(id);
}

function bar(id) {
    try {
        throw {
            name: "Exception",
            message: "oooh damn!" + id
        }
    } catch (e) {
        console.error(e.name, e.message);
    }
}

フィドルの例を参照してください: http://jsfiddle.net/amyamy86/Am8mf/

だから、もしそうなら:

setTimeout(function () { foo(1); }, 10);
setTimeout(function () { foo(2); }, 10);

それから戻ってきます:

Exception oooh damn!1
Exception oooh damn!2

または私がする場合:

setTimeout(function () { foo(1); }, 10);
setTimeout(function () { foo(2); }, 9);

それから戻ってきます:

Exception oooh damn!2
Exception oooh damn!1

編集 #2 IDを引数として渡す必要がないようにするには:

var currentId = null;
function foo() {
    var id = currentId;        // since it's copied over to 'id', we don't care about 'currentId' anymore
    var bar = function() {
        try {
            throw {
                name: "Exception",
                message: "oooh damn!" + id
            }
        } catch (e) {
            console.error(e.name, e.message);
        }
    }
    /* some statements */
    bar();
}

setTimeout(function () {
    currentId = 1;
    foo();
}, 10);
setTimeout(function () {
    currentId = 2;
    foo();
}, 10);

つまり、currentIdは共有変数ですが、 が終了した瞬間に設定されsetTimeout()、関数を実行します。

そうやって:

setTimeout(function () {
    currentId = 1;
    foo();
}, 10);
setTimeout(function () {
    currentId = 2;
    foo();
}, 9);

それから戻ってきます:

Exception oooh damn!2
Exception oooh damn!1
于 2013-03-28T17:47:52.533 に答える
1

without using try/catch, stacks, or modifying existing code, all you can so is use a smarter setTimeout:

(function(){
  if(!setTimeout.id){
  var old=setTimeout, hits=0;
  setTimeout=function timeout(code, delay, id){ 
     var count=hits++;
     setTimeout.calls=setTimeout.calls||{};
     setTimeout.calls[id||count]=code;
     return old(function(){ 
           setTimeout.id=id||count; 
           code.call? code() : Function(code)(); 
     }, delay);  
  };
  setTimeout.id=true;
 }//end setTimeout patcher

}());


function foo() {     /* some statements */ 
    bar(); 
} 


function bar() { throw new Error("oooh damn! #"+setTimeout.id+"\t"+setTimeout.calls[setTimeout.id] ); }

setTimeout(function() { foo(); }, 20, "more");
setTimeout(function() { foo(); }, 10, "something");
setTimeout(function() { foo(); }, 20);
setTimeout(function() { foo(); }, 10);

basically, this makes a property of setTimeout available, id. since JS is single-threaded, it SHOULD be impossible for this property to get over-written before your function completes, so the "last" set setTimeout.id is the "current" one while a timed-out function runs.

you can pass a third argument (forget browser-quirk currying for this) to manually specify an ID, or let an index be assigned to it. This means each call has a unique identifier, which might be all you need to debug. If you need the code itself, my setTimeout provides a .calls property, a lookup that that lets you view the code/function evaluated under that ID.

于 2013-05-01T20:58:57.657 に答える