例として
var runInfinite = function(){
while(1)
{
// Do stuff;
}
};
setTimeout(runInfinite, 0);
無限に実行されているこのrunInfinite関数形式を破ることは可能ですか?つまり、フラグやreturnステートメントを使用せずに、この関数を別の関数から強制終了することは可能ですか?
例として
var runInfinite = function(){
while(1)
{
// Do stuff;
}
};
setTimeout(runInfinite, 0);
無限に実行されているこのrunInfinite関数形式を破ることは可能ですか?つまり、フラグやreturnステートメントを使用せずに、この関数を別の関数から強制終了することは可能ですか?
答えはいいえだ。JavaScriptはシングルスレッドであるため(私が疑うあまり一般的でない実装を使用している場合を除き)、外部からループ(または他のコードブロック)を壊すことはできません。
実行中のjavascript関数を「強制終了」する直接的な方法はありません。
while(1)
ループを置き換える必要がありますが、考えられる回避策は次のとおりです。
var i = 0; // for testing purposes
var toCall = "runInfinite()";
function runInfinite(){
// do stuff
console.log(i++);
setTimeout(function(){ eval(toCall); }, 100); // or whatever timeout you want
}
setTimeout(function(){ eval(toCall); }, 0); // start the function
setTimeout(function(){ toCall = ""; }, 5000); // "kill" the function
eval()
使用することは悪い習慣であると考えられていることは知っていますが、その考えは明確でなければなりません。関数は、変数を使用して自分自身を呼び出します(再帰的ではないため、setTimeout()
) 。toCall
この変数の設定を解除したら、外部から強制終了します。
これらの変数と関数をクラスにラップして、「kill」関数を実装できます。
ブラウザでテストしました。
AFAIK、while(1)ブロックは文字通りスレッドをブロックし、他のものを実行することを許可しません。経験以外のソースはありませんが、Chrome開発者ツールキットを使用すると、browser-javascriptがシングルスレッドであるため、ctrl+shift+i
入力すると他のすべてがブロックされます。while(1){}
ただし、を使用しているnode.js
場合は、マルチスレッド機能を備えているため、使用できる場合があります。誰かが十分に精通していてnode.js
、答え/編集する気があるなら、それを選んでください。私はそれを完全に使用したことがありません。
あなたが本当に望んでいない理由。しかし、多分あなたはそれを間違ってやっています。可能であれば使用しないようにしてくださいwhile(1)
。関数の最後で、外部フラグがトリガーされたがブレークボタンが設定されていない場合は関数を再度呼び出すか、そうでない場合は戻ります。
return を使用して、関数を現在の実行から停止することができますが、あなたの場合は使用できません。
あなたの場合、あなたはあなたの関数がtry / catchブロックに包まれていることを試みることができます、あなたはあなたがその現在の実行を終了することができることに基づいて、あなたの関数がいつ無限になるかを知ることができます。
これはまったく同じではないことは認めますが、ECMA-262にはJavascriptジェネレーターとJavascriptイテレーターがあります。関数をジェネレーター関数に置き換えることができれば、壊れやすい機能を簡単に実装できます。
function execWithTimeout(iter, timeout = 100) {
const limit = Date.now() + timeout
for (const output of iter) {
console.log(output)
if (Date.now() > limit) throw(new Error("Timeout reached"))
}
}
let runInfinite = function * () {
let i = 0
while (1) {
yield i++
}
}
execWithTimeout(runInfinite())