私が書いた関数を呼び出すJavaScript関数がありますが、そのコードを制御することはできません。私の関数はDOMを使用してiFrameを生成し、そのsrcを定義してから、別のDOM要素に追加します。ただし、関数が戻る前に、つまり含まれている関数の継続的な実行を許可する前に、iFrameが完全にロードされていることが不可欠です。
これが私が試したことと、なぜそれらが機能しないのかです:
1. SetTimeoutオプション:
99.999%の確率で、これが答えです。実際のところ、私がJavaScriptで指導してきた過去10年間、私は常にこのオプションを使用するためにコードをリファクタリングできると主張してきましたが、そうでないシナリオが存在するとは信じていませんでした。さて、ようやく見つけました!問題は、関数がインラインで呼び出されているため、iFrameの読み込みが完了する前に次の行が実行されると、スクリプトが完全に無効になり、スクリプトが完了した瞬間から外部スクリプトが続行されることです。ある種のコールバックは機能しません
2.「何もしない」ループ:
while(// iFrameがロードされていない){//何もしない}で使用するこのオプション。理論的には、フレームがロードされるまでこれは戻りません。問題は、これがすべてのリソースを占有するため、iFrameが読み込まれないことです。このトリックは、ひどく専門的ではない、汚いなど、インライン遅延が必要な場合に機能しますが、完了するには外部スレッドが必要なため、機能しません。
FFでは、数秒後にスクリプトが一時停止し、応答しないスクリプトがあることを示すアラートがポップアップ表示されます。そのアラートが発生している間、iFrameをロードしてから関数を返すことができますが、ブラウザーを10秒間フリーズさせてから、ユーザーにエラーを正しく閉じるように要求することはできません。
3.モデルダイアログ:
FFポップアップで関数の実行を停止しながらiFrameを読み込むことができたという事実に触発され、それについて考えると、モーダルダイアログが実行を停止し、他のスレッドを続行できるようにする方法であることがわかりました。 !!素晴らしいので、他のモーダルオプションを試すことにしました。alert()のようなものは美しく機能します!ポップアップすると、10分の1秒しか表示されなくても、iFrameは完了でき、すべてが正常に機能します。また、1/10秒では不十分な場合に備えて、ソリューション2のwhileループにモデルダイアログを配置できます。これにより、iFrameが時間内に読み込まれるようになります。甘いね?スクリプトを実行するために、ユーザーが却下するための非常に専門的でないダイアログをポップアップする必要があるという事実を除いて。私はこの行動のこの費用便益について自分自身と戦いました、しかし、その後、1つのページでコードが10回呼び出されるというシナリオに遭遇しました。ページにアクセスする前に10個のアラートを閉じる必要がありますか?!これは、90年代後半のスクリプトキディページを思い出させるものであり、オプションではありません。
4.他にも数え切れないほどの遅延スクリプトが
あります。約10個のjQuery遅延またはスリープ関数があり、それらのいくつかは実際には非常に巧妙に開発されていますが、どれも機能しませんでした。いくつかのプロトタイプオプション、そして繰り返しますが、私が見つけたものはどれもそれを行うことができませんでした!十数かそこらの他のライブラリとフレームワークは、私が必要なものを持っていると主張しましたが、残念ながら、それらはすべて私に誤った希望を与えるために共謀しました。
組み込みのモデルダイアログは実行を停止し、他のスレッドは続行できるため、ユーザー入力なしで同じことを行うためのコードアクセス可能な方法が必要であると確信しています。
コードは文字通り数千行から数千行であり、独自仕様であるため、この問題の小さな例を作成しました。変更できる唯一のコードはonlyThingYouCanChange関数にあることに注意することが重要です。
テストファイル:
<html>
<head>
</head>
</html>
<body>
<div id='iFrameHolder'></div>
<script type='text/javascript'>
function unChangeableFunction()
{
new_iFrame = onlyThingYouCanChange(document.getElementById('iFrameHolder'));
new_iFrame_doc = (new_iFrame.contentWindow || new_iFrame.contentDocument);
if(new_iFrame_doc.document)new_iFrame_doc=new_iFrame_doc.document;
new_iFrame_body = new_iFrame_doc.body;
if(new_iFrame_body.innerHTML != 'Loaded?')
{
//The world explodes!!!
alert('you just blew up the world! Way to go!');
}
else
{
alert('wow, you did it! Way to go!');
}
}
var iFrameLoaded = false;
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
unChangeableFunction();
</script>
</body>
blank_frame.html:
<html>
<head>
</head>
<body style='margin:0px'>Loaded?</body>
</html>
これが私がレスポンダーからのアイデアを組み合わせることから作った答えです!あなたたち最高!
変更を許可された関数の新しいソース:
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
if (window.XMLHttpRequest)
{
AJAX=new XMLHttpRequest();
}
else
{
AJAX=new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX)
{
AJAX.open("GET", 'slow_page.php', false);
AJAX.send(null);
}
else
{
alert('something is wrong with AJAX!');
}
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
slow_page.php:
<?
usleep(100000);//sleep for 1/10th of a second, to allow iFrame time to load without DOSing our own server!
?>
その関数の外に変更できるものは何もないと述べたことに注意したいと思います。phpページを追加すると、その「ルール」に違反しましたが、場合によってはそれを行うことができました。それができなかった場合は、 slow_page.phpの代わりにblank_frame.htmlを呼び出すことができ、同じ量の応答があったと仮定すると、1回だけ呼び出す必要がありました(つまり、フレームの読み込みごとに2回)。 iFrameの読み込み時間。何らかの理由でiFrameの読み込みが遅い場合は、2ceと呼ばれることがあります(サーバーへの合計3回の呼び出し)