如何在node.js中使用jQuery ajax调用

71
这与使用Node.js流传输数据类似,但我觉得那个问题的答案不够充分。我试图使用jQuery的ajax调用(get、load、getJSON)在页面和node.js服务器之间传输数据。我可以从浏览器访问该地址并看到“Hello World!”,但当我尝试从我的页面中尝试时,它失败了,并显示我没有收到任何响应。我设置了一个简单的测试页和hello world示例来测试这个问题:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>get test</title> 
</head>
<body>
    <h1>Get Test</h1>
    <div id="test"></div>

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js"></script>
    <script>
        $(document).ready(function() {
            //alert($('h1').length);
            $('#test').load('http://192.168.1.103:8124/');
            //$.get('http://192.168.1.103:8124/', function(data) {                
            //  alert(data);
            //});
        });
    </script>
</body>
</html>
并且
var http = require('http');

http.createServer(function (req, res) {
    console.log('request received');
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(8124);

1
我们需要知道你正在加载的文件中有什么内容 - 加载文件中的代码是如何执行的? - mattsven
4个回答

86

如果你的简单测试页面位于与你的hello world node.js示例不同的协议/域名/端口上,那么你正在进行跨域请求并违反了同源策略,因此你的jQuery ajax调用(get和load)会静默失败。要使这个跨域请求正常工作,你应该使用基于JSONP的格式。例如node.js代码:

var http = require('http');

http.createServer(function (req, res) {
    console.log('request received');
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('_testcb(\'{"message": "Hello world!"}\')');
}).listen(8124);

并且客户端使用JavaScript/jQuery:

$(document).ready(function() {
    $.ajax({
        url: 'http://192.168.1.103:8124/',
        dataType: "jsonp",
        jsonpCallback: "_testcb",
        cache: false,
        timeout: 5000,
        success: function(data) {
            $("#test").append(data);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            alert('error ' + textStatus + " " + errorThrown);
        }
    });
});

还有其他方法可以使它工作,例如设置反向代理或完全使用像express这样的框架构建您的 Web 应用程序。


非常感谢你的回答,yojimbo。这真的帮了我很多。我已经发布了一个带有一些额外内容的答案。 - Michael Dausmann
用Express构建Node.js应用程序如何解决跨域请求问题? - angry kiwi
Node.js 可以在“长轮询”模式下运行吗?我的意思是,不断地从 MySQL 请求数据,同时如果没有接收到数据,则继续进行轮询循环,并在收到数据时增加请求的 id 以启动新的“长轮询”。这种情况可能吗? - droplet
1
@Petsoukos 长轮询(作为一种基于Web的推送技术)可以通过几个模块在node.js中实现(例如socket.io,它还支持其他传输方式),但是直接轮询MySQL将非常低效。我建议您查看一些发布/订阅机制,例如redis,可以用于此目的。 - yojimbo87
嗨yojimbo,你的代码在所有浏览器中都能正常工作,但当我将同样的代码用于我的Android PhoneGap应用时,它显示超时,并且总是出现错误:不在成功中,请问你能否建议可能的问题。提前致谢。 - Rahul
显示剩余3条评论

9
感谢yojimbo的回答。除了他的示例外,我想使用jquery的$.getJSON方法将一个随机回调放在查询字符串中,因此我还想在Node.js中解析它。 我还想传递一个对象并使用stringify函数。
这是我的客户端代码。
$.getJSON("http://localhost:8124/dummy?action=dostuff&callback=?",
function(data){
  alert(data);
},
function(jqXHR, textStatus, errorThrown) {
    alert('error ' + textStatus + " " + errorThrown);
});

这是我的服务器端Node.js。
var http = require('http');
var querystring = require('querystring');
var url = require('url');

http.createServer(function (req, res) {
    //grab the callback from the query string   
    var pquery = querystring.parse(url.parse(req.url).query);   
    var callback = (pquery.callback ? pquery.callback : '');

    //we probably want to send an object back in response to the request
    var returnObject = {message: "Hello World!"};
    var returnObjectString = JSON.stringify(returnObject);

    //push back the response including the callback shenanigans
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(callback + '(\'' + returnObjectString + '\')');
}).listen(8124);

你的代码运行得很好。请注意,使用text/plain作为内容类型会导致mime错误。将内容类型更改为application/javascript即可解决该问题。 - payling

3

我猜测你的html页面托管在不同的端口上。大多数浏览器都要求遵守同源策略,即加载的文件必须与加载文件在同一个端口上。


1
在服务器端使用类似以下的东西:
http.createServer(function (request, response) {
    if (request.headers['x-requested-with'] == 'XMLHttpRequest') {
        // handle async request
        var u = url.parse(request.url, true); //not needed

        response.writeHead(200, {'content-type':'text/json'})
        response.end(JSON.stringify(some_array.slice(1, 10))) //send elements 1 to 10
    } else {
        // handle sync request (by server index.html)
        if (request.url == '/') {
            response.writeHead(200, {'content-type': 'text/html'})
            util.pump(fs.createReadStream('index.html'), response)
        } 
        else 
        {
            // 404 error
        }
    }
}).listen(31337)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接