异步' Post'中的回调函数问题。

时间:2016-05-10 00:46:37

标签: javascript

我是javascript的新手,我遇到了在上一行完成之前执行一行代码的问题。据我所知,我需要创建一个回调函数,使最后一行等待前一行完成。我的程序接受用户输入并使用异步'帖子'将其发送到网站,然后返回一条消息。当我将以下两行代码放在一起时,我的原始问题出现了:

    req.send(JSON.stringify(payload))
    event.preventDefault();

preventDefault()不等待send()函数完成。我试过实现一个回调函数,但我也遇到了问题。

    function sendReq(callback){
        req.send(JSON.stringify(payload), function(){
            callback();
        });
    }
    sendReq(function(){
        event.preventDefault();
    });

我们非常感谢任何建议。这是我的整个代码以防万一。

    var apiKey = "appid=fa7d80c48643dfadde2cced1b1be6ca1";
    document.addEventListener('DOMContentLoaded', bindButtons);
    function bindButtons(){
        document.getElementById('dataSubmit').addEventListener('click', function(event){
            var req = new XMLHttpRequest();
            var payload = {longUrl:null};
            payload.longUrl = document.getElementById('inputData').value;
            req.open('POST', 'http://httpbin.org/post&' + apiKey, true);
            req.setRequestHeader('Content-Type', 'application/json');

            var response = JSON.parse(req.responseText);
            req.addEventListener('load',function(){
                if(req.status >= 200 && req.status < 400){
                    document.getElementById('outputData').textContent = response.longUrl;
                } 
                else 
                    console.log("Error in network request");
            });
            function sendReq(callback){
                req.send(JSON.stringify(payload), function(){
                    callback();
                });
            }
            sendReq(function(){
                event.preventDefault();
            });
        });
    }

1 个答案:

答案 0 :(得分:2)

你误解了回调是如何运作的。查看recurial.com上的这篇文章:Understanding callback functions in Javascript

你不能在JavaScript [*]中“等待” - 由于名为"Run-to-completion" semantics的东西:你的代码总是运行以响应事件(例如“DOMContentLoaded”,“单击“,或XHR的”加载“),在您当前运行的代码完成之前(通常是return - 从最外层的函数 - 事件处理程序),将不再处理任何事件 - 并且不会处理其他事件处理程序。

长时间运行的JS代码会使网页冻结,这就是为什么要求您首先编写异步请求的原因 - 同步XHR会导致页面冻结,而代码会等待服务器的响应。

为了避免冻结并仍然完成工作,您可以将代码构造为一系列回调:在启动异步请求后,您将从当前函数返回并让系统在收到响应时回拨您。您可以使用响应的唯一时刻是回调,通过回调的定义。

在您的情况下,指示响应可用的回调是load处理程序。这就是你应该移动var response = JSON.parse(req.responseText);行的地方。

PS。 preventDefault()与您的情况完全无关,它不能用于“等待send()函数完成”;它用于处理事件的情况(例如onsubmit的{​​{1}}),并且您希望在此事件触发时阻止浏览器默认执行某些操作(在<form>示例中 - 好 - 提交表格。)

PPS。在弄清楚基础知识并开始编写连续超过2个回调的代码后,查找“promises”。

PPPS。 [*] 忽略这句话,我添加它只是为了准确,因为它只会让你在这个阶段迷惑:你不能在JavaScript中“等待”,除非你写的是{{3和/或使用当前不可用的"generator")。