异步中的回调函数出现问题'张贴'

Trouble with callback function in asynchronous 'Post'

本文关键字:问题 张贴 回调 函数 异步      更新时间:2023-09-26

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

    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();
            });
        });
    }

您误解了回调的工作方式。查看recursial.com上的这篇文章:了解Javascript 中的回调函数

您不能在JavaScript[*]中"等待"-这是由于一种名为"Run to completion"的语义:您的代码总是响应事件(如"DOMContentLoaded"、"click"或XHR的"load")运行,并且在您当前运行的代码完成之前,不会再处理任何事件,也不会处理任何其他事件处理程序(通常通过return从最外层的函数——事件处理程序)。

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

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

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


PS。preventDefault()与您的情况完全无关,不能用于"等待send()函数完成";它用于处理一个事件(例如<form>onsubmit),并且您希望在该事件触发时阻止浏览器默认执行的操作(在<form>示例中——好吧——提交表单)的情况。

PPS。在您了解了基础知识并开始编写连续有2个以上回调的代码后,请查找"promise"。

PPPS。[*]忽略这句话,我添加它只是为了准确起见,因为它只会在现阶段让你感到困惑:除非你正在编写"生成器"和/或使用当前不可用的async/await,否则你不能在JavaScript中"等待"。