UNPKG

bat-ria

Version:

RIA extension for Brand Ads Team

322 lines (288 loc) 9.94 kB
/** * @file 请求发送器 * @author Justineo(justice360@gmail.com) */ define(function (require) { var ajax = require('er/ajax'); var Deferred = require('er/Deferred'); var Dialog = require('esui/Dialog'); var u = require('underscore'); var loc = require('../location'); var io = {}; /** * 常规请求流程中的hook如下: * * io.request(url, data, options) * │ * ├───── io.hooks.beforeRequest(data) ───┐ * │ │ * │<────────────── data ─────────────────┘ * │ * ├───── io.hooks.afterResponse(data) ───┐ * │ │ * │<────────────── data ─────────────────┘ * │ * └─────────────────┐ * ┌──── success ────♦──── failure ────┐ * │ │ * ├─ io.hooks.afterSuccess(data) ─┐ ├─ io.hooks.afterFailure(message) ─┐ * │ │ │ │ * │<──────────── data ────────────┘ │<───────────── message ───────────┘ * │ │ * ├───────────────────────────────────┘ * ● */ io.hooks = {}; /** * 后端返回的结果代码对应的类型 * * @enum {string} */ var CodeType = { 0: 'SUCCESS', 1: 'GLOBAL', 2: 'FIELD', 3: 'REDIRECT', 4: 'NO_SESSION' }; /** * 最小的自定义错误代码 * 小于此代码的均保留为预定义类型,大于等于此代码作为自定义处理 * * @type {number} */ var MINIMAL_CUSTOM_FAIL_CODE = 100; var SERVER_ERROR = getGlobalError('服务器错误'); var PARSE_ERROR = getGlobalError('数据解析失败'); var SCHEMA_ERROR = getGlobalError('数据格式错误'); var UNKNOWN_ERROR = getGlobalError('未知错误'); /** * 生成全局错误对象 * * @param {string} message 错误提示信息 * @return {Object} 全局错误对象 */ function getGlobalError(message) { return { success: false, message: { global: message } }; } /** * 适配新NMP接口返回的结果 * * @param {Object} data 后端返回的数据对象 * @return {Object} 转换过后符合前端逻辑的对象 */ io.prepareResponse = function (data) { if (typeof data.code !== 'undefined') { // 有code时认为是新版接口 var status = CodeType[data.code]; if (!status) { if (data.code < MINIMAL_CUSTOM_FAIL_CODE) { // 非预定义类型,未知错误 return UNKNOWN_ERROR; } else { // 自定义类型错误 var message = data.message || {}; message.code = data.code; return { success: false, message: message }; } } else { if (status === 'SUCCESS') { var result = { success: true, message: data.message, result: data.result || data.page }; return u.purify(result); } else { return { success: false, message: data.message }; } } } else if (typeof data.success !== 'undefined') { return data; } else { return SCHEMA_ERROR; } }; /** * 跳转到主页 */ function gotoIndex() { var url = '/index.html'; if (typeof io.hooks.filterIndexUrl === 'function') { url = io.hooks.filterIndexUrl(url) || url; } loc.assign(url); } /** * 处理服务端响应成功的情况 * * @param {Object} rawData 转换后的后端响应对象 * @return {meta.Promise} 处理后的Promise */ function requestSuccessHandler(rawData) { var data = io.prepareResponse(rawData); if (typeof io.hooks.afterResponse === 'function') { data = io.hooks.afterResponse(data) || data; } if ((data.success + '') !== 'true') { var message = data.message; var title; var content; var onok; var needAlert = true; if (typeof message.global !== 'undefined') { title = '系统提示'; content = message.global; } else if (typeof message.noSession !== 'undefined') { title = '系统超时'; content = message.noSession; onok = gotoIndex; } else if (typeof message.redirect !== 'undefined') { if (message.redirect === '') { title = '登录超时'; content = '登录超时,请重新登录!'; onok = function() { loc.reload(true); }; } else { loc.assign(message.redirect); return; } } else if (typeof message.field !== 'undefined' || typeof message.code !== 'undefined') { // 字段错误不需要弹窗提示,直接在表单中处理 // 自定义错误也在后面的过程中自行处理 needAlert = false; } else { // last resort title = '系统提示'; content = '未知错误'; } if (needAlert) { Dialog.alert(u.purify({ title: title, content: content, onok: onok })); } if (typeof io.hooks.afterFailure === 'function') { message = io.hooks.afterFailure(message) || message; } message = requestCompleteHandler(message) || message; return Deferred.rejected(message); } else { // 成功状态 if (typeof io.hooks.afterSuccess === 'function') { data = io.hooks.afterSuccess(data) || data; } var result = data.page || data.result; result = requestCompleteHandler(result) || result; return Deferred.resolved(result); } } /** * 处理服务端响应失败的情况 * 转换为成功响应,返回错误提示处理 * * @param {meta.Promise} fakeXHR 请求的Promise * @return {meta.Promise} 处理后的Promise */ function requestFailureHandler(fakeXHR) { var status = fakeXHR.status; var error; if (status < 200 || (status >= 300 && status !== 304)) { // 服务器没有正常返回 error = SERVER_ERROR; } else { error = PARSE_ERROR; } return requestSuccessHandler(error); } /** * 处理服务端响应完成的情况 * 不管成功失败均执行 * * @param {Object|meta.Promise} data 成功时为返回的数据对象,失败时为请求Promise * @return {Mixed} 处理后的输入参数 */ function requestCompleteHandler(data) { if (typeof io.hooks.afterComplete === 'function') { data = io.hooks.afterComplete(data) || data; } return data; } /** * 向服务端发起请求 * * @param {string} url 请求URL * @param {Object} data 请求参数 * @param {Object} options 请求选项 * @return {meta.Promise} 请求Promise */ io.request = function(url, data, options) { var defaults = { url: url, data: data, dataType: 'json', charset: 'utf-8' }; options = options ? u.defaults(options, defaults) : defaults; options.data = u.extend(options.data, data); if (typeof io.hooks.beforeRequest === 'function') { options = io.hooks.beforeRequest(options) || options; } return ajax.request(options) .then( requestSuccessHandler, requestFailureHandler ); }; /** * 以GET方式向服务端发起请求 * * @param {string} url 请求URL * @param {Object} data 请求参数 * @param {Object} options 请求选项 * @return {meta.Promise} 请求Promise */ io.get = function(url, data, options) { u.extend(options, { method: 'GET' }); return this.request(url, data, options); }; /** * 以POST方式向服务端发起请求 * * @param {string} url 请求URL * @param {Object} data 请求参数 * @param {Object} options 请求选项 * @return {meta.Promise} 请求Promise */ io.post = function(url, data, options) { u.extend(options, { method: 'POST' }); return this.request(url, data, options); }; // return模块 return io; });