将事件侦听器传递给onreadystatechange

时间:2016-04-11 19:49:56

标签: javascript

我在用户会话过期后提交表单时实现了“登录以继续”功能,但我遇到了一些我不太了解的事情。

当我将提交监听器添加到表单时,它在提交之前需要3次提交尝试(登录时):第1次,没有任何内容打印到控制台;第二个提交打印'预防表单提交',第三个提交最终允许提交继续。之后,每2个提交将起作用,第一个显示上面的控制台行。

但是,如果我将'this'传递给onreadystatechange函数,它的工作方式与我期望的每次一样 - 唯一的问题是我在JS控制台中遇到'SyntaxError:missing formal parameter'错误,显然因为我提供的是一个值来代替参数名称。

所以我的问题是:如何正确地执行此操作,如果我不向函数提供'this'(事件监听器所附加的当前表单元素),为什么它不起作用? ?

我不想在这个特定项目中使用JQuery或任何外部库,所以请不要在你的答案中使用任何。

form.addEventListener('submit', function(e) {
    var xmlhttp = new XMLHttpRequest();
    // xmlhttp.onreadystatechange = function() { // doesn't work the way I want
    xmlhttp.onreadystatechange = function(this) { // works the way I want
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            if (xmlhttp.responseText === 'true') {
                form.setAttribute('allow_submit', 'true');
                form.submit();
            } else {
                form.setAttribute('allow_submit', 'false');
            }
        }
    }
    xmlhttp.open("POST", "xml_request_router.php", true);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.send('route_id=active_session_check');
    console.log("Preventing form submission");
    if (form.getAttribute('allow_submit') !== 'true') {
        e.preventDefault();
    }
});

我尝试过使用回调并将参数传递给它,但行为与上面完全相同。这是我的尝试:

function stateChanged(xmlhttp, form) {
    if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
        if (xmlhttp.responseText === 'true') {
            form.setAttribute('allow_submit', 'true');
            form.submit();
        } else {
            form.setAttribute('allow_submit', 'false');
        }
    }
}

// and here's how I called it from the event listener:
xmlhttp.onreadystatechange = function() { // adding 'this' results in correct behavior
    stateChanged(xmlhttp, form);
}

编辑:以下是我检索表单元素的方法:

var forms = document.getElementsByTagName('form');
for (i = 0; i < forms.length; i++) {
    var form = forms[i];
    // rest of code follows from here
编辑:为了防止其他人来到这里寻找解决方案,我能够让闭包正常工作的唯一方法是将NodeList转换为数组并迭代它:

function nodeListToArray(nl) {
    var i = nl.length, arr = new Array(i);
    for(; i--; arr[i] = nl[i]);
    return arr;
}
var forms = document.getElementsByTagName('form');
nodeListToArray(forms).forEach(function(form) {
    form.addEventListener('submit', function(e) {
        // this way does NOT work:
        // return function(e, this) {
            // original logic here
        // }
        // but this way DOES:
        return notSureWhyThisIsNecessary(e, this);
    });
});

function notSureWhyThisIsNecessary(e, form) {
    // original logic here, i.e. xmlhttp request etc.
}

因此,如果像我自己一样,JavaScript闭包(特别是在上述情况下)对你来说仍然有些神秘,即使在阅读了大量关于它们的文章之后,上面的代码片段也许会有所帮助。欢呼声。

0 个答案:

没有答案