ajax post関数を作成しましたが、これを1回呼び出すと、渡されるコールバック関数が3回呼び出されることになります。 コールバックが複数回呼び出されるのはなぜですか?
クロージャを使用して1つのグローバル変数の下で同様の機能をラップする「モジュール」JavaScriptパターンを使用しようとしています。私のajaxモジュールは独自のファイルであり、次のようになります。
var ajax = (function (XMLHttpRequest) {
"use strict";
var done = 4, ok = 200;
function post(url, parameters, callback) {
var XHR = new XMLHttpRequest();
if (parameters === false || parameters === null || parameters === undefined) {
parameters = "";
}
XHR.open("post", url, true);
XHR.setRequestHeader("content-type", "application/x-www-form-urlencoded");
XHR.onreadystatechange = function () {
if (XHR.readyState === done && XHR.status === ok) {
callback(XHR.responseText);
}
};
XHR.send(parameters);
}
// Return the function/variable names available outside of the module.
// Right now, all I have is the ajax post function.
return {
post: post
};
}(parent.XMLHttpRequest));
メインアプリケーションもそれ自身のファイルです。例として、次のようになります。
// Start point for program execution.
(function (window, document, ajax) {
"use strict";
ajax.post("php/paths.php", null, function () { window.alert("1"); });
}(this, this.document, parent.ajax));
ご覧のとおり、依存関係をローカル変数/名前空間として取り込もうとしています。これを実行すると、アラートボックスが3回ポップアップします。
この問題の原因がajax関数自体なのか、アーキテクチャ全体(またはその両方)なのかわからないので、どちらかについてコメントや考えをいただければ幸いです。
プログラムの主要部分を無名関数からアンラップしようとしましたが、それは役に立ちませんでした。前もって感謝します!
編集:
これがHTMLファイル全体なので、私が<script>
'を含める順序を確認できます。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="expires" conent="0" />
<title>Mapalicious</title>
<link href="css/main.css" type="text/css" rel="stylesheet" />
<script src="js/raphael.js"></script>
</head>
<body>
<div id="map"></div>
<script src="js/promise.js"></script>
<script src="js/bigmap.js"></script>
<script src="js/ajax.js"></script>
<script src="js/init.js"></script>
</body>
</html>
編集2:
私の例ではタイプミスがあり、変更しました
(function (window, document, bigmap, ajax) {
に
(function (window, document, ajax) {
編集3:
onreadystatechange
準備完了状態をコンソールに記録するように関数を変更しました。
XHR.onreadystatechange = function () {
console.log("readyState: " + XHR.readyState);
if (XHR.readyState === done && XHR.status === ok) {
callback(XHR.responseText);
}
};
Google Chromeでコードをステップ実行すると、コールバックが3回呼び出され、コンソールは次のログを記録します。
readyState: 4
readyState: 4
readyState: 4
ただし、ページを通常どおり実行し、ステップスルーしない場合、関数は期待どおりに機能し、コールバックを1回だけ実行します。この場合、コンソールは次のログを記録します。
readyState: 2
readyState: 3
readyState: 3
readyState: 4
だから今私の質問は、コードをステップスルーするときにコールバックが複数回呼び出されるのはなぜですか?
解決済み:
この質問をしたとき、デバッグ中にコードをステップ実行しているときにのみ発生していることに気づきませんでした。
つまり、状態は3回変化しましたが、実行がブレークポイントによって遅延しているため、3つの関数すべてで、実際に変化が発生したときの状態ではonreadystatechange
なく、現在の状態4が表示されます。
要点は、onreadystatechange
変更はその状態が何であるかを保存しないということです。readyState
代わりに、プログラムが中断された場合でも、実行時にを読み取り、その間に状態が再び変化します。
したがって、AJAXには、完全同期コードで使用するものとは異なるデバッグ手法が必要です...しかし、おそらくすでにそれを知っているでしょう。
ここで助けてくれたすべての人に感謝します。