如何重写Backbone.ajax方法以使用cordova-plugin-advanced-HTTP?
解决Backbone.js + PhoneGap中CORS Origin问题:用cordova-plugin-advanced-HTTP重写Backbone.ajax
你遇到的核心问题是浏览器的同源策略安全限制——浏览器不允许手动修改Origin这类敏感请求头,所以只能通过原生插件绕过,因为插件的请求是在原生层发起的,不受浏览器CORS规则约束。下面是完整的重写方案:
步骤1:确认插件已安装
先确保你已经正确安装了cordova-plugin-advanced-HTTP:
cordova plugin add cordova-plugin-advanced-HTTP
步骤2:重写Backbone.ajax方法
我们需要把Backbone默认的jQuery Ajax调用替换成插件API,同时保持Backbone期望的Deferred/Promise接口一致,这样现有Model/Collection的fetch()、save()等方法无需修改就能正常工作:
Backbone.ajax = function(options) { // 创建jQuery Deferred对象,保持和Backbone原生Ajax的Promise兼容 const deferred = Backbone.$.Deferred(); // 整理插件所需的参数 const httpOptions = { url: options.url, headers: options.headers || { 'Accept': 'application/json' }, data: options.data || {} }; // 处理不同HTTP请求方法 switch(options.method?.toUpperCase() || 'GET') { case 'GET': cordova.plugin.http.get( httpOptions.url, httpOptions.data, httpOptions.headers, (response) => { // 尝试解析JSON响应,兼容非JSON场景 try { response.data = JSON.parse(response.data); } catch(e) {} deferred.resolve(response); }, (error) => { // 统一错误格式,适配Backbone的错误处理逻辑 deferred.reject({ status: error.status, responseText: error.error, responseJSON: error.data ? JSON.parse(error.data) : null }); } ); break; case 'POST': // 默认设置JSON格式的Content-Type,可根据后端需求调整 if (!httpOptions.headers['Content-Type']) { httpOptions.headers['Content-Type'] = 'application/json'; httpOptions.data = JSON.stringify(httpOptions.data); } cordova.plugin.http.post( httpOptions.url, httpOptions.data, httpOptions.headers, (response) => { try { response.data = JSON.parse(response.data); } catch(e) {} deferred.resolve(response); }, (error) => { deferred.reject({ status: error.status, responseText: error.error, responseJSON: error.data ? JSON.parse(error.data) : null }); } ); break; // 按需扩展PUT、DELETE等方法 case 'PUT': if (!httpOptions.headers['Content-Type']) { httpOptions.headers['Content-Type'] = 'application/json'; httpOptions.data = JSON.stringify(httpOptions.data); } cordova.plugin.http.put( httpOptions.url, httpOptions.data, httpOptions.headers, (response) => { try { response.data = JSON.parse(response.data); } catch(e) {} deferred.resolve(response); }, (error) => { deferred.reject({ status: error.status, responseText: error.error, responseJSON: error.data ? JSON.parse(error.data) : null }); } ); break; case 'DELETE': cordova.plugin.http.delete( httpOptions.url, httpOptions.data, httpOptions.headers, (response) => { try { response.data = JSON.parse(response.data); } catch(e) {} deferred.resolve(response); }, (error) => { deferred.reject({ status: error.status, responseText: error.error, responseJSON: error.data ? JSON.parse(error.data) : null }); } ); break; default: deferred.reject(new Error(`Unsupported HTTP method: ${options.method}`)); } // 返回Deferred的Promise,保持接口一致性 return deferred.promise(); };
关键细节说明
- 接口兼容:用jQuery的
Deferred封装插件的回调,确保现有代码里的done()、fail()或者async/await逻辑无需修改。 - 请求头与序列化:默认配置JSON格式的请求头和序列化逻辑,如果你的后端需要表单格式,只需修改
Content-Type并去掉JSON.stringify即可。 - 错误统一:把插件返回的错误格式转换成Backbone熟悉的结构,避免现有错误处理逻辑崩溃。
- 执行时机:这段重写代码要在
deviceready事件触发后执行,确保cordova.plugin.http对象已经初始化完成。
内容的提问来源于stack exchange,提问作者Sreekanth




