AJAX跨域请求获取JSON数据主要有以下几种实现方法:
服务器端设置响应头允许跨域访问:
// 服务器端示例(Node.js)
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*'); // 允许所有域名
// 或指定域名
// res.header('Access-Control-Allow-Origin', 'https://example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
客户端正常使用AJAX:
// 前端请求
fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data));
function jsonp(url, callback) {
const callbackName = 'jsonp_callback_' + Math.random().toString(36).substr(2);
window[callbackName] = function(data) {
delete window[callbackName];
document.body.removeChild(script);
callback(data);
};
const script = document.createElement('script');
script.src = url + (url.includes('?') ? '&' : '?') + 'callback=' + callbackName;
document.body.appendChild(script);
}
// 使用
jsonp('https://api.example.com/data?param=value', function(data) {
console.log('获取到的数据:', data);
});
在自己的服务器上创建代理接口:
// Node.js Express 代理示例
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/api/proxy', async (req, res) => {
try {
const response = await axios.get('https://api.example.com/data', {
params: req.query
});
res.json(response.data);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
前端调用自己的代理接口:
fetch('/api/proxy?param=value')
.then(response => response.json())
.then(data => console.log(data));
import axios from 'axios';
// 配置默认设置
axios.defaults.headers.common['Content-Type'] = 'application/json';
// 简单请求
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('请求失败:', error);
});
// 带配置的请求
axios.get('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer token'
},
params: {
page: 1,
limit: 10
}
});
$.ajax({
url: 'https://api.example.com/data',
type: 'GET',
dataType: 'json',
crossDomain: true,
headers: {
'Accept': 'application/json'
},
success: function(data) {
console.log('成功:', data);
},
error: function(xhr, status, error) {
console.error('失败:', error);
}
});
对于复杂请求(如带自定义头或非简单方法),需要处理OPTIONS预检请求:
// 服务器端处理预检请求
app.options('*', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
res.sendStatus(200);
});
// 客户端
fetch('https://api.example.com/data', {
credentials: 'include', // 发送cookies
headers: {
'Authorization': 'Bearer ' + token
}
});
// 服务器端
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Origin', 'https://yourdomain.com'); // 不能使用*
class ApiClient {
constructor(baseURL) {
this.baseURL = baseURL;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const defaultOptions = {
headers: {
'Content-Type': 'application/json',
},
mode: 'cors',
credentials: 'same-origin', // 或 'include'
};
try {
const response = await fetch(url, {
...defaultOptions,
...options,
headers: {
...defaultOptions.headers,
...options.headers,
},
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('请求失败:', error);
throw error;
}
}
get(endpoint, params = {}) {
const queryString = new URLSearchParams(params).toString();
const url = queryString ? `${endpoint}?${queryString}` : endpoint;
return this.request(url, { method: 'GET' });
}
post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data),
});
}
}
// 使用
const api = new ApiClient('https://api.example.com');
api.get('/data', { page: 1, limit: 10 })
.then(data => console.log(data));
*,指定允许的域名
安全性考虑:验证请求来源,使用适当的认证机制
错误处理:添加完善的错误处理逻辑
性能优化:考虑缓存策略,减少不必要的请求
考虑使用反向代理:在Nginx或Apache中配置代理