epikTrash: AJAX/JSON

Hallo ich habe ein Problem mit einem Javascript: Ich möchte beim Ausführen einer Funktion getMail(1); im onload Bereich des HTML Dokuments eine Funtkion ausführen, die eine Datei "header/1/" läd in der sich ein JSON Objekt befindet. Beim Ausführen passiert nichts. Es gibt auch keine Fehler in den Fehlerkonsolen von FF 4 und Opera 11.01. Der Funktionsaufruf schein bei der Funktion addMail() zu scheitern, da dort die if Bedingung nicht erfüllt wird. index.htm:

<!DOCTYPE html>
    <head>
        <title>m&ouml;p</title>
        <script type="text/javascript" src="json_sans_eval.js"></script>
        <script type="text/javascript" src="tmpjs.js"></script>
    </head>

    <body onload="getMail(1);">
        <div>
			<div id="nav">
			</div>
			<div id="mailwrapper"></div>
        </div>
    </body>
</html>

tmpjs.js:

<!--
			function getXmlHttpRequestObject() {
				if (window.XMLHttpRequest) {
					return new XMLHttpRequest();
				} else if(window.ActiveXObject) {
					return new ActiveXObject("Microsoft.XMLHTTP");
				} else {
					alert("Dein Browser unterstützt keine XmlHttpRequest Objekte. Besser du wechselst auf Firefox oder Opera.<br />Your browser doesn't support the XmlHttpRequest object.  Better upgrade to Firefox or Opera.");
				}
			}			
			var receiveReq = getXmlHttpRequestObject();
			var mailArray = new Array();
			mailArray[0] = '';
			function handleContent() {
				if (receiveReq.readyState == 4) {
					document.getElementById('mailwrapper').innerHTML = receiveReq.responseText;
				}
			}
			function showContent(id) {
				if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
					receiveReq.open("GET", 'content/'+id+'/', true);
					receiveReq.onreadystatechange = handleContent;
					receiveReq.send(null);
				}			
			}
			function addMail(id) {
				if (receiveReq.readyState == 4) {
					mailArray[id] = jsonParse(receiveReq.responseText);
					refreshMails;
				}
			}
			function deleteMail(id) {
				mailArray[id] = '';
				refreshMails;
			}
			function getMail(id) {
				if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
					receiveReq.open("GET", 'header/'+id+'/', true);
					receiveReq.onreadystatechange = addMail(id);
					receiveReq.send(null);
				}
			}
			function refreshMails() {
				var returnVar = '';
				for(var i = mailArray.length; i > 0; --i) {
					if(mailArray[i] != '') {
						returnVar += '<a href="javascript:showContent('+mailArray[i].id+')"><div id="'+mailArray[i].id+'" class="element"><div class="top"><div class="name">'+mailArray[i].from+'</div><div class="time">'+mailArray[i].time+'</div></div><div class="bottom">'+mailArray[i].subject+'</div></div></a>';
					}
				}
				document.getElementById('nav').innerHTML = returnVar;
			}
			function rateMail(id, rate) { /* TODO */
				refreshMails;
			}
-->

json_sans_eval.js:

// This source code is free for use in the public domain.
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

// http://code.google.com/p/json-sans-eval/

/**
 * Parses a string of well-formed JSON text.
 *
 * If the input is not well-formed, then behavior is undefined, but it is
 * deterministic and is guaranteed not to modify any object other than its
 * return value.
 *
 * This does not use `eval` so is less likely to have obscure security bugs than
 * json2.js.
 * It is optimized for speed, so is much faster than json_parse.js.
 *
 * This library should be used whenever security is a concern (when JSON may
 * come from an untrusted source), speed is a concern, and erroring on malformed
 * JSON is *not* a concern.
 *
 *                      Pros                   Cons
 *                    +-----------------------+-----------------------+
 * json_sans_eval.js  | Fast, secure          | Not validating        |
 *                    +-----------------------+-----------------------+
 * json_parse.js      | Validating, secure    | Slow                  |
 *                    +-----------------------+-----------------------+
 * json2.js           | Fast, some validation | Potentially insecure  |
 *                    +-----------------------+-----------------------+
 *
 * json2.js is very fast, but potentially insecure since it calls `eval` to
 * parse JSON data, so an attacker might be able to supply strange JS that
 * looks like JSON, but that executes arbitrary javascript.
 * If you do have to use json2.js with untrusted data, make sure you keep
 * your version of json2.js up to date so that you get patches as they're
 * released.
 *
 * @param {string} json per RFC 4627
 * @param {function (this:Object, string, *):*} opt_reviver optional function
 *     that reworks JSON objects post-parse per Chapter 15.12 of EcmaScript3.1.
 *     If supplied, the function is called with a string key, and a value.
 *     The value is the property of 'this'.  The reviver should return
 *     the value to use in its place.  So if dates were serialized as
 *     {@code { "type": "Date", "time": 1234 }}, then a reviver might look like
 *     {@code
 *     function (key, value) {
 *       if (value && typeof value === 'object' && 'Date' === value.type) {
 *         return new Date(value.time);
 *       } else {
 *         return value;
 *       }
 *     }}.
 *     If the reviver returns {@code undefined} then the property named by key
 *     will be deleted from its container.
 *     {@code this} is bound to the object containing the specified property.
 * @return {Object|Array}
 * @author Mike Samuel <mikesamuel@gmail.com>
 */
var jsonParse = (function () {
  var number
      = '(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)';
  var oneChar = '(?:[^\\0-\\x08\\x0a-\\x1f\"\\\\]'
      + '|\\\\(?:[\"/\\\\bfnrt]|u[0-9A-Fa-f]{4}))';
  var string = '(?:\"' + oneChar + '*\")';

  // Will match a value in a well-formed JSON file.
  // If the input is not well-formed, may match strangely, but not in an unsafe
  // way.
  // Since this only matches value tokens, it does not match whitespace, colons,
  // or commas.
  var jsonToken = new RegExp(
      '(?:false|true|null|[\\{\\}\\[\\]]'
      + '|' + number
      + '|' + string
      + ')', 'g');

  // Matches escape sequences in a string literal
  var escapeSequence = new RegExp('\\\\(?:([^u])|u(.{4}))', 'g');

  // Decodes escape sequences in object literals
  var escapes = {
    '"': '"',
    '/': '/',
    '\\': '\\',
    'b': '\b',
    'f': '\f',
    'n': '\n',
    'r': '\r',
    't': '\t'
  };
  function unescapeOne(_, ch, hex) {
    return ch ? escapes[ch] : String.fromCharCode(parseInt(hex, 16));
  }

  // A non-falsy value that coerces to the empty string when used as a key.
  var EMPTY_STRING = new String('');
  var SLASH = '\\';

  // Constructor to use based on an open token.
  var firstTokenCtors = { '{': Object, '[': Array };

  var hop = Object.hasOwnProperty;

  return function (json, opt_reviver) {
    // Split into tokens
    var toks = json.match(jsonToken);
    // Construct the object to return
    var result;
    var tok = toks[0];
    var topLevelPrimitive = false;
    if ('{' === tok) {
      result = {};
    } else if ('[' === tok) {
      result = [];
    } else {
      // The RFC only allows arrays or objects at the top level, but the JSON.parse
      // defined by the EcmaScript 5 draft does allow strings, booleans, numbers, and null
      // at the top level.
      result = [];
      topLevelPrimitive = true;
    }

    // If undefined, the key in an object key/value record to use for the next
    // value parsed.
    var key;
    // Loop over remaining tokens maintaining a stack of uncompleted objects and
    // arrays.
    var stack = [result];
    for (var i = 1 - topLevelPrimitive, n = toks.length; i < n; ++i) {
      tok = toks[i];

      var cont;
      switch (tok.charCodeAt(0)) {
        default:  // sign or digit
          cont = stack[0];
          cont[key || cont.length] = +(tok);
          key = void 0;
          break;
        case 0x22:  // '"'
          tok = tok.substring(1, tok.length - 1);
          if (tok.indexOf(SLASH) !== -1) {
            tok = tok.replace(escapeSequence, unescapeOne);
          }
          cont = stack[0];
          if (!key) {
            if (cont instanceof Array) {
              key = cont.length;
            } else {
              key = tok || EMPTY_STRING;  // Use as key for next value seen.
              break;
            }
          }
          cont[key] = tok;
          key = void 0;
          break;
        case 0x5b:  // '['
          cont = stack[0];
          stack.unshift(cont[key || cont.length] = []);
          key = void 0;
          break;
        case 0x5d:  // ']'
          stack.shift();
          break;
        case 0x66:  // 'f'
          cont = stack[0];
          cont[key || cont.length] = false;
          key = void 0;
          break;
        case 0x6e:  // 'n'
          cont = stack[0];
          cont[key || cont.length] = null;
          key = void 0;
          break;
        case 0x74:  // 't'
          cont = stack[0];
          cont[key || cont.length] = true;
          key = void 0;
          break;
        case 0x7b:  // '{'
          cont = stack[0];
          stack.unshift(cont[key || cont.length] = {});
          key = void 0;
          break;
        case 0x7d:  // '}'
          stack.shift();
          break;
      }
    }
    // Fail if we've got an uncompleted object.
    if (topLevelPrimitive) {
      if (stack.length !== 1) { throw new Error(); }
      result = result[0];
    } else {
      if (stack.length) { throw new Error(); }
    }

    if (opt_reviver) {
      // Based on walk as implemented in http://www.json.org/json2.js
      var walk = function (holder, key) {
        var value = holder[key];
        if (value && typeof value === 'object') {
          var toDelete = null;
          for (var k in value) {
            if (hop.call(value, k) && value !== holder) {
              // Recurse to properties first.  This has the effect of causing
              // the reviver to be called on the object graph depth-first.

              // Since 'this' is bound to the holder of the property, the
              // reviver can access sibling properties of k including ones
              // that have not yet been revived.

              // The value returned by the reviver is used in place of the
              // current value of property k.
              // If it returns undefined then the property is deleted.
              var v = walk(value, k);
              if (v !== void 0) {
                value[k] = v;
              } else {
                // Deleting properties inside the loop has vaguely defined
                // semantics in ES3 and ES3.1.
                if (!toDelete) { toDelete = []; }
                toDelete.push(k);
              }
            }
          }
          if (toDelete) {
            for (var i = toDelete.length; --i >= 0;) {
              delete value[toDelete[i]];
            }
          }
        }
        return opt_reviver.call(holder, key, value);
      };
      result = walk({ '': result }, '');
    }

    return result;
  };
})();

in der Datei auf Pfad 'header/1/' befindet sich folgender Inhalt: {"from": "webteam@asf.de","subject": "Willkommen 122","time": "17:39"}

Danke, wenn jemand weiß, warum (receiveReq.readyState == 4) ind der Funktion addMail immer falsch ist.

Lg epikTrash

  1.   			receiveReq.onreadystatechange = addMail(id);  
    

    Traditionelles Event-Handling
    Häufiger Fehler: Handler-Funktion direkt aufrufen

    Du rufst hier die Handlerfunktion in dem Moment auf, wo du eigentlich den readystatechange-Handler registrieren willst.

    Als Handler wird der *Rückgabewert* des Funktionsaufrufs addMail(1) verwendet. Der ist undefined, also findet keine Event-Überwachung statt.

    Du musst hier eine Funktion zuweisen. Wenn du Parameter übergeben willst, dann mit einer weiteren Funktion:

    receiveReq.onreadystatechange = function () {
       addMail(id);
    };

    json_sans_eval.js:

    Dieser JSON-Parser ist veraltet. Aktuelle Browser haben längst native Parser. Die sind am schnellsten und sichersten. Nimm daher lieber json2.js bzw. json_parse.js.

    * This library should be used whenever security is a concern (when JSON may
    * come from an untrusted source), speed is a concern, and erroring on malformed
    * JSON is *not* a concern.

    Das trifft auf deinen Anwendungsfall anscheinend nicht zu.
    Ich denke nicht, dass der Geschwindigkeitsaspekt in deinem Fall ins Gewicht fällt.

    Mathias