// streamRequestMixin.js
export default {
data() {
return {
xhr: null, // 用于存储XMLHttpRequest实例
cancelStream: null,//用于中止请求
isFirstUpdate:true,//是否是第一次得到数据
};
},
methods: {
startStreamedRequest(prefix, url,requestParams, onData, onEnd, onError, onCancel) {
var that = this
if (this.xhr && this.xhr.readyState !== 4) {
// 如果当前有正在进行的请求,先取消它
this.xhr.abort();
}
this.xhr = new XMLHttpRequest();
// 监听数据传输过程中的数据块
this.xhr.onprogress = function (event) {
if (event.lengthComputable) {
// 这里可以根据需要处理数据...
// 但由于onprogress可能频繁触发,我们可能不需要每次都处理responseText
// 实际应用中,你可能需要更复杂的逻辑来处理流式数据
}
};
// 为了处理流式数据,我们通常监听readystatechange事件而不是onload
// 因为我们希望在数据到达时立即处理,而不是等待整个响应完成
this.xhr.onreadystatechange = function () {
if (this.readyState === 3) { // LOADING状态
console.log('this.response',this.response);
const jsonObjects = this.response.match(/{.*?}/g)
const jsonData = jsonObjects.map(jsonStr => JSON.parse(jsonStr));
onData(jsonData)
} else if (this.readyState === 4) { // DONE状态
onEnd();
// 清理
this.xhr = null;
that.isFirstUpdate = true
}
};
// 初始化请求
let token = that.$getToken()//获取token
let requestUrl = window.location.origin + prefix + url
this.xhr.open('POST', requestUrl, true);
this.xhr.responseType = 'text';
this.xhr.setRequestHeader("Authorization", "Bearer " + token)
this.xhr.setRequestHeader('Content-type', 'application/json;charset=utf-8');
// 将参数序列化为JSON字符串
let paramsJson = JSON.stringify(requestParams);
this.xhr.send(paramsJson);
// 返回一个函数,用于取消请求
return function cancelRequest() {
if (this.xhr && (this.xhr.readyState !== 0 && this.xhr.readyState !== 4)) {
this.xhr.abort();
if (onCancel) {
onCancel();
}
this.xhr = null; // 清理XMLHttpRequest实例
that.isFirstUpdate = true
}
}.bind(this); // 确保cancelRequest中的this指向mixin的上下文
},
},
beforeDestroy() {
if (this.cancelStream && typeof this.cancelStream === 'function') {
this.cancelStream();
console.log('The stream request has been canceled');
}
}
};
使用举例
this.cancelStream = this.startStreamedRequest('xxx','/api/xxxx/xxxxxxx',{ askMainId: 'xxxxxxxx' },data => {
this.dealResponseData(data)
}, () => {
this.aiLoading = false
console.log('Stream ended');
}, error => {
this.aiLoading = false
this.$message({type:'error',message:error})
}, () => {
this.aiLoading = false
});