欢迎光临韵绾网
详情描述

AJAX跨域请求获取JSON数据主要有以下几种实现方法:

1. CORS(跨域资源共享)【推荐】

服务器端设置响应头允许跨域访问:

// 服务器端示例(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));

2. JSONP(仅限GET请求)

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

3. 服务器端代理

在自己的服务器上创建代理接口:

// 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));

4. 使用现代JavaScript库

使用Axios:

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

使用jQuery:

$.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);
  }
});

5. 处理预检请求(Preflight)

对于复杂请求(如带自定义头或非简单方法),需要处理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);
});

6. 带凭据的请求(Cookies/Authentication)

// 客户端
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'); // 不能使用*

7. 封装通用的跨域请求函数

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

最佳实践建议

优先使用CORS:这是W3C标准,支持所有HTTP方法 生产环境限制源:避免使用通配符*,指定允许的域名 安全性考虑:验证请求来源,使用适当的认证机制 错误处理:添加完善的错误处理逻辑 性能优化:考虑缓存策略,减少不必要的请求 考虑使用反向代理:在Nginx或Apache中配置代理

注意事项

  • 浏览器对CORS的支持:现代浏览器都支持,但IE10以下需要额外处理
  • 复杂的CORS请求会触发预检请求(OPTIONS)
  • 确保服务器正确配置CORS头部
  • 考虑HTTPS协议的跨域限制
相关帖子
2026年,哪些行业更普遍实行13薪制度,哪些行业则侧重发放年终奖?
2026年,哪些行业更普遍实行13薪制度,哪些行业则侧重发放年终奖?
面对不断上涨的生活成本,普通家庭如何利用公开数据进行开支规划?
面对不断上涨的生活成本,普通家庭如何利用公开数据进行开支规划?
南阳市工商解非|注册公司专业代办,欢迎电话咨询,不成功不收费
南阳市工商解非|注册公司专业代办,欢迎电话咨询,不成功不收费
南阳市公司注册资本变更办理流程-中小微企业注册,专业代办服务,收费合理
南阳市公司注册资本变更办理流程-中小微企业注册,专业代办服务,收费合理
文化中的蝙蝠意象:从福寿象征到西方吸血鬼传说演变
文化中的蝙蝠意象:从福寿象征到西方吸血鬼传说演变
金华市高新企业申报代办-公司执照代办,一站式代办服务,不成功不收费
金华市高新企业申报代办-公司执照代办,一站式代办服务,不成功不收费
未来五年,订阅制商业模式在哪些领域可能会发生新的变化?
未来五年,订阅制商业模式在哪些领域可能会发生新的变化?
无锡市公司注销办理|装修公司注册,快速办理,欢迎电话咨询
无锡市公司注销办理|装修公司注册,快速办理,欢迎电话咨询
平台用工模式下,骑手的社保缴费责任在法律上应当如何界定与划分?
平台用工模式下,骑手的社保缴费责任在法律上应当如何界定与划分?
宜宾市商标注册代办-工商代理,专业代办公司
宜宾市商标注册代办-工商代理,专业代办公司
阜新市危险化学品经营许可证代办服务-个体户营业执照代办,不成功不收费,专业代办
阜新市危险化学品经营许可证代办服务-个体户营业执照代办,不成功不收费,专业代办
在决定提交申请前,有哪些前置的自我评估问题可以帮助我们更清醒?
在决定提交申请前,有哪些前置的自我评估问题可以帮助我们更清醒?
安康市专业网站建设公司@网站搜索引擎优化,专业建站公司
安康市专业网站建设公司@网站搜索引擎优化,专业建站公司
延边公司减资流程|股份有限公司注册,全程代办,快速办理
延边公司减资流程|股份有限公司注册,全程代办,快速办理
如果对摇奖结果有疑问,可以通过哪些正规渠道进行咨询或申诉?
如果对摇奖结果有疑问,可以通过哪些正规渠道进行咨询或申诉?
烫伤后第一时间用凉水冲,这个关键步骤背后的科学原理是什么?
烫伤后第一时间用凉水冲,这个关键步骤背后的科学原理是什么?
2026年,公众对残疾人使用机动轮椅车出行的接纳与支持度有何变化?
2026年,公众对残疾人使用机动轮椅车出行的接纳与支持度有何变化?
七台河市企业网站开发@精准获客软件,优秀设计团队
七台河市企业网站开发@精准获客软件,优秀设计团队
苏州市建筑资质代办|注册公司价格,专业一站式代办服务
苏州市建筑资质代办|注册公司价格,专业一站式代办服务