t-comm
Version:
专业、稳定、纯粹的工具库
314 lines (309 loc) • 9.97 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var tslib_es6 = require('../tslib.es6-01322ba9.js');
var sse_helper = require('./helper.js');
/**
* 解析 H5 环境下的 SSE 数据流
* @param {Object} params - 参数对象
* @param {Function} params.success - 成功回调函数
* @param {Function} params.fail - 失败回调函数
* @param {Function} params.complete - 完成回调函数
* @param {Response} params.response - 响应对象
* @returns {Promise} 返回一个 Promise,处理 SSE 数据流
*/
var parseSSEChunkInH5 = function parseSSEChunkInH5(_a) {
var success = _a.success,
fail = _a.fail,
complete = _a.complete,
response = _a.response;
return tslib_es6.__awaiter(void 0, void 0, void 0, function () {
function processText(_a) {
var done = _a.done,
value = _a.value;
return tslib_es6.__awaiter(this, void 0, void 0, function () {
var chunk, buffers, i, line, response_1;
return tslib_es6.__generator(this, function (_b) {
if (done) {
complete === null || complete === void 0 ? void 0 : complete(true);
return [2 /*return*/, Promise.resolve()];
}
chunk = decoder.decode(value);
buffers = chunk.toString().split(/\r?\n/);
i = 0;
while (i < buffers.length) {
line = buffers[i];
response_1 = line.slice(5);
success === null || success === void 0 ? void 0 : success(response_1, line);
buffers.splice(i, 1);
}
return [2 /*return*/, reader.read().then(processText)];
});
});
}
var reader, decoder;
return tslib_es6.__generator(this, function (_b) {
if (!(response === null || response === void 0 ? void 0 : response.ok)) {
// 失败中不调用完成,如果需要,业务自行在 fail 中调用
// 防止业务在 fail 中调用 complete 时,complete 被调用两次
fail === null || fail === void 0 ? void 0 : fail({
response: response
});
// 抛出错误以便链式调用中的下一个.catch()处理
return [2 /*return*/, Promise.reject(new Error('Request failed'))];
}
reader = response.body.getReader();
decoder = new TextDecoder();
if (!reader) {
return [2 /*return*/, Promise.reject(new Error('[SSE] 获取reader失败'))];
}
return [2 /*return*/, reader.read().then(processText)];
});
});
};
/**
* 在 H5 环境下发起 SSE 请求的核心函数
* @param {Object} params - 参数对象
* @param {string} params.url - 请求 URL
* @param {any} params.data - 请求数据
* @param {Function} params.success - 成功回调函数
* @param {Function} params.fail - 失败回调函数
* @param {Function} params.complete - 完成回调函数
* @returns {Promise} 返回一个 Promise,包含响应对象
*/
function fetchSSECoreInH5(_a) {
var url = _a.url,
data = _a.data,
success = _a.success,
fail = _a.fail,
complete = _a.complete;
return new Promise(function (resolve, reject) {
var controller = new AbortController();
fetch(url, {
method: 'POST',
headers: {
accept: 'application/json, text/plain, */*',
'content-type': 'application/json;charset=UTF-8'
},
body: JSON.stringify(data),
credentials: 'include',
// mode: 'cors',
signal: controller.signal
}).then(function (response) {
resolve(response);
parseSSEChunkInH5({
response: response,
success: success,
fail: fail,
complete: complete
});
})["catch"](function (err) {
reject(err);
});
});
}
/**
* 获取登录 Cookie
* @param {Function} isTestEnv - 是否为测试环境的函数
* @returns {string} 返回拼接后的 Cookie 字符串
*/
function getLoginCookie(isTestEnv) {
var headerCookie = '';
var testEnv = isTestEnv === null || isTestEnv === void 0 ? void 0 : isTestEnv();
var cookieSuffix = testEnv ? '@test' : '@prod';
if (uni.getStorageSync("request-mp-set-cookie".concat(cookieSuffix))) {
headerCookie = uni.getStorageSync("request-mp-set-cookie".concat(cookieSuffix));
}
if (uni.getStorageSync("user-info-sessionid".concat(cookieSuffix))) {
// 如果是测试环境,需要设置到tiplogin_sessionid_test
var sessionKey = 'tiplogin_sessionid';
if (isTestEnv === null || isTestEnv === void 0 ? void 0 : isTestEnv()) {
sessionKey = 'tiplogin_sessionid_test';
}
headerCookie += ";".concat(sessionKey, "=").concat(uni.getStorageSync("user-info-sessionid".concat(cookieSuffix)), ";");
}
return headerCookie;
}
/**
* 解析 MP 环境下的 SSE 数据块
* @param {Object} params - 参数对象
* @param {string} params.chunk - 数据块
* @param {Fail} [params.fail] - 失败回调函数
* @param {Success} [params.success] - 成功回调函数
*/
var parseSSEChunkInMP = function parseSSEChunkInMP(_a) {
var chunk = _a.chunk,
fail = _a.fail,
success = _a.success;
var buffers = chunk.toString().split(/\r?\n/);
var i = 0;
try {
while (i < buffers.length) {
var line = buffers[i];
var response = line.slice(5);
success === null || success === void 0 ? void 0 : success(response, line);
buffers.splice(i, 1);
}
} catch (err) {
fail === null || fail === void 0 ? void 0 : fail(false);
}
};
/**
* 在 MP 环境下发起 SSE 请求的核心函数
* @param {RequestParams} params - 请求参数
* @returns {Promise} 返回一个 Promise,包含请求任务对象
*/
function fetchSSECoreInMP(_a) {
var url = _a.url,
data = _a.data,
success = _a.success,
_fail = _a.fail,
complete = _a.complete,
isTestEnv = _a.isTestEnv;
return new Promise(function (resolve) {
// 开启分块接收,模拟 SSE
var requestTask = wx.request({
url: url,
method: 'POST',
responseType: 'arraybuffer',
enableChunked: true,
header: {
Accept: 'text/event-stream',
'content-type': 'application/json;charset=UTF-8',
cookie: getLoginCookie(isTestEnv),
'Cache-Control': 'no-cache'
},
data: data,
success: function success(res) {
console.log('[SSE] success: ', res);
complete === null || complete === void 0 ? void 0 : complete(true, res);
},
fail: function fail(err) {
console.log('[SSE] fail: ', err);
_fail === null || _fail === void 0 ? void 0 : _fail(err);
}
});
// 监听数据到达事件
requestTask.onChunkReceived(function (res) {
// res.data 是 ArrayBuffer,需要转换为字符串
var chunk = sse_helper.ab2str(res.data);
parseSSEChunkInMP({
chunk: chunk,
fail: _fail,
success: success
});
});
resolve(requestTask);
});
}
/**
* 发起 SSE 请求的核心函数,根据环境自动选择 H5 或 MP 实现
* @param {RequestParams} params - 请求参数
* @param {string} params.url - 请求地址
* @param {Object} params.data - 请求数据
* @param {Function} params.success - 成功回调
* @param {Function} params.fail - 失败回调
* @param {Function} params.complete - 完成回调
* @returns {Promise} 返回一个 Promise,包含请求任务或响应对象
* @example
* ```ts
* import { isTestEnv } from '@tencent/pmd-tools/lib/env';
* import { cookie } from '@tencent/pmd-tools/lib/storage';
* import { safeJsonParse } from 't-comm/es/json';
*
* import { fetchSSECore, type RequestParams } from 't-comm/es/sse';
*
* // 检查是否结束,业务自定义
* function checkFinish(str) {
* const data: any = safeJsonParse(str);
* return data?.status === 3;
* }
*
* // 业务二次封装,把自己的请求数据、自定义的处理数据的逻辑放进去
* export function sendChatMessage({
* input,
* sessionId,
* extraInfo,
* expectedOp,
*
* success,
* fail,
* complete,
* }: {
* input: string;
* sessionId?: string;
* extraInfo?: string;
* expectedOp?: Record<string, any>;
*
* success?: (data: any) => void;
* fail?: RequestParams['fail'];
* complete?: RequestParams['complete'];
* }) {
* const origin = isTestEnv() ? 'https://xx.com' : 'https://xx.com';
* const url = `${origin}/xx.xx.xx.xx/xx?g_app_tk=${cookie.get('tip_token')}&tstamp=${Date.now()}`;
* const reqData = {
* input,
* session_id: sessionId,
* extra_info: extraInfo,
* expected_op: expectedOp,
* };
*
* const parsedSuccess = (str, fullStr) => {
* const data: any = safeJsonParse(str);
* const fullData: any = safeJsonParse(fullStr);
*
* if (checkFinish(str)) {
* complete?.(str);
* return;
* }
*
* // 检查是否失败,业务自定义
* if (fullData?.err_msg) {
* fail?.(data);
* return;
* }
*
* success?.(data);
* };
*
* return fetchSSECore({
* url,
* data: reqData,
* success: parsedSuccess,
* fail,
* complete,
* isTestEnv,
* });
* }
*
* ```
*/
function fetchSSECore(_a) {
var url = _a.url,
data = _a.data,
success = _a.success,
fail = _a.fail,
complete = _a.complete,
isTestEnv = _a.isTestEnv;
if (typeof wx !== 'undefined' && typeof wx.request === 'function' && typeof fetch === 'undefined' && typeof AbortController === 'undefined') {
return fetchSSECoreInMP({
url: url,
data: data,
success: success,
fail: fail,
complete: complete,
isTestEnv: isTestEnv
});
}
return fetchSSECoreInH5({
url: url,
data: data,
success: success,
fail: fail,
complete: complete
});
}
exports.fetchSSECore = fetchSSECore;
exports.fetchSSECoreInH5 = fetchSSECoreInH5;
exports.fetchSSECoreInMP = fetchSSECoreInMP;
exports.parseSSEChunkInH5 = parseSSEChunkInH5;
exports.parseSSEChunkInMP = parseSSEChunkInMP;