通过 jQuery Ajax 方法访问 Node.js 服务遇到的问题

通过 jQuery Ajax 方法访问 Node.js 服务遇到的问题

疑问:请求是成功的,但是跳到 error 中执行,请问各位大侠这是怎么回事啊 直接上代码 Node.js 代码:

http.createServer(function(req, res) {
    var url = parse(req.url),
        pathname = url.pathname;

    console.log('Request URL: http://127.0.0.1:8090' + url.href);
    //解析URL参数到resource对象
    req.resource = restparser.parse(pathname);
    //resource.id 存在,表示是RESTful的请求
    if (req.resource.id) {
        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        restrouter.router(req, res, function(stringfyResult) {
            res.end(stringfyResult);
        });
    } else {
        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        console.log('Request URL is not in RESTful style!');
        res.end('Request URL is not in RESTful style!');
    }
}).listen(8090, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8090/');

前端请求

$.ajax({
    type: "GET",
    url: "http://127.0.0.1:8090/resources/group",
    contentType: "application/json; charset=utf-8",
    dataType: "jsonp",
    success: function(json) {
        console.log(json);
    },
    error: function(error) {
        console.log(error);
    }
});

7 回复

问题描述

你提到的代码中,虽然请求成功,但仍然进入了 error 回调函数。这种情况通常是由几个潜在原因导致的,包括跨域请求、服务器返回的错误状态码或数据格式不匹配等。

分析与解决方案

跨域问题

首先检查是否是因为跨域(CORS)问题导致的。jQuery 的 dataType: "jsonp" 用于处理 JSONP 请求,这种请求类型是为了支持跨域请求。然而,如果你的服务器并没有正确处理 JSONP 请求,这可能会导致问题。

数据格式不匹配

其次,检查你的服务器返回的数据格式是否符合 jsonp 的预期。jsonp 通常需要服务器返回一个包裹在回调函数中的 JSON 对象。例如:

callback({"key": "value"});

确保你的服务器代码能够生成这样的输出。

示例代码修改

Node.js 代码

const http = require('http');
const url = require('url');
const querystring = require('querystring');

http.createServer((req, res) => {
    const parsedUrl = url.parse(req.url);
    const pathname = parsedUrl.pathname;
    
    console.log(`Request URL: http://127.0.0.1:8090${parsedUrl.href}`);
    
    // 解析 URL 参数到 resource 对象
    req.resource = querystring.parse(pathname.slice(1));
    
    // resource.id 存在,表示是 RESTful 的请求
    if (req.resource.id) {
        res.writeHead(200, {
            'Content-Type': 'application/javascript'
        });
        
        restrouter.router(req, res, (stringfyResult) => {
            res.end(`callback(${stringfyResult})`);
        });
    } else {
        res.writeHead(400, {
            'Content-Type': 'text/plain'
        });
        console.log('Request URL is not in RESTful style!');
        res.end('Request URL is not in RESTful style!');
    }
}).listen(8090, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8090/');

前端请求

$.ajax({
    type: "GET",
    url: "http://127.0.0.1:8090/resources/group?callback=?",
    contentType: "application/json; charset=utf-8",
    dataType: "jsonp",
    success: function(json) {
        console.log(json);
    },
    error: function(error) {
        console.log(error);
    }
});

解释

  1. Node.js 代码:增加了对 req.resource.id 的判断,并且确保当请求成功时,返回的数据被包裹在一个回调函数中。
  2. 前端请求:确保 dataType 设置为 "jsonp",并且在 URL 中包含 callback=?,以让 jQuery 自动处理 JSONP 的回调函数名。

这样可以确保前端能够正确接收到后端返回的数据,并进入 success 回调函数。如果问题仍然存在,请检查网络请求的具体细节,例如 HTTP 状态码和响应头信息。


你…

用 JSONP…你服务端没实现啊… JSONP 的标准啊…能不报错吗…

…嗯…简单说一下 JSONP 吧… 你 jQuery Ajax 过来.应该会用一个 callback 参数的你输出的时候得 用 callback 的值包一层…

例如

?callback=xxx

你返回的时候得

xxx(你的内容)

就像楼上说的,你用的是JSONP。 AJAX 和 JSONP 是不一样的。由于AJAX无法跨域请求。所以才产生的JSONP。 看你的代码,不存在跨域的问题。所以dataType那里直接用"json"就行。

当然,如果你一定要用jsonp的话,就像楼上说的,服务器端实现callback。

我监听了8090端口,如果我用localhost:8090/…html访问的话会被nodejs监听到,所以我用了跨域,请问该怎么避免node监听我地址栏的html请求呢

嗯,谢谢指出问题,之前一直没用过跨域的访问,这次因为我node监听了8090端口,如果我使用http://…:8090/…html 来访问的话会被node监听一次,请问这个可以避免吗

根据你的描述,问题可能出在 dataType: "jsonp" 上。jsonp 主要用于解决浏览器同源策略限制,使得客户端可以从其他域名获取数据。而你的服务器端并未实现 JSONP 的响应格式。通常,JSONP 需要在服务器端返回一个函数调用包裹的数据。

示例解决方案:

1. 修改前端代码为普通的 dataType: "json"

$.ajax({
    type: "GET",
    url: "http://127.0.0.1:8090/resources/group",
    contentType: "application/json; charset=utf-8",
    dataType: "json",  // 改为普通的 json
    success: function(json) {
        console.log(json);
    },
    error: function(error) {
        console.log(error);
    }
});

2. 如果需要使用 JSONP,请修改 Node.js 代码

http.createServer(function(req, res) {
    var url = parse(req.url),
        pathname = url.pathname;

    console.log('Request URL: http://127.0.0.1:8090' + url.href);
    
    // 解析URL参数到resource对象
    req.resource = restparser.parse(pathname);

    // resource.id 存在,表示是RESTful的请求
    if (req.resource.id) {
        res.writeHead(200, {
            'Content-Type': 'application/javascript'
        });

        restrouter.router(req, res, function(stringfyResult) {
            // 假设回调函数名为 callback
            const callbackName = req.query.callback || 'callback';
            res.end(`${callbackName}(${stringfyResult})`);
        });
    } else {
        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        console.log('Request URL is not in RESTful style!');
        res.end('Request URL is not in RESTful style!');
    }
}).listen(8090, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8090/');

解释:

  1. 前端:将 dataTypejsonp 改为 json 可以避免不必要的复杂性。
  2. 后端:如果确实需要支持 JSONP,需确保服务器返回的数据被正确包装在一个 JavaScript 函数调用中。这里假设回调函数名为 callback,你可以在请求中指定实际的回调函数名。

这样可以解决 error 回调被触发的问题。

回到顶部