背景
在钉钉工作台组件中,我们需要实现一个公共的JWT组件,其他组件在获取数据之前需要通过该组件获取JWT,并使用JWT来调用接口返回接口数据。这样可以减少每个请求中用户数据转换的次数,同时在多个钉钉组件之间实现身份验证信息的传递。
存在问题
在组件初始化阶段,我们使用以下方法去获取JWT组件的数据:
getSdk().triggerCustomEvent('dingdingworkbench/request', data);
然而,有时候JWT组件尚未完全加载,导致上述方法失效,进而导致其他组件无法正确加载数据。
问题分析
目前工作台组件的加载顺序依赖于网络请求的完成情况,即先完成加载的组件资源会先执行。官方并未提供监听组件加载状态的方法。
解决方案
- 等待JWT组件加载完成后,触发其他组件的初始化,并设定一个超时时间。
- 如果在限定时间内未收到消息通知,组件可以自行发起一次请求。
通过以上优化方案,我们可以解决组件间数据传递的同步问题,确保在合适的时机获取到JWT并进行后续操作,从而提升组件间交互的稳定性和可靠性。
//JWT组件
Component({
data: {
ddJWT:'',
refreshData:'',
componentInitSate:{},// 组件初始化状态,记录各组件是否已初始化
hasReceivedNotification:false,// 是否收到所有组件的通知
},
props: {
componentName: '',
componentProps: {
gateWayJWT: {},
componentNames:"LatestNews,Document,Column",// 需要发送消息通知的组件列表
},
},
didMount() {
let _this = this
getLifecycleSdk().didMount(this.props.componentName);
this.iniJWT()
this.requestParams = (returnData) => {
console.log('returnData',returnData)
if(returnData){
// 通知返回,监听 componentName/request ,触发说明 componentName 组件初始化完成
let componentName = returnData.pluginName.split('/')[0];
let componentInitState = this.data.componentInitState;
componentInitState[componentName] = true;
let hasReceivedNotification = Object.values(componentInitState).every(state => state);
this.setData({
hasReceivedNotification: hasReceivedNotification,
componentInitState: componentInitState
});
}
_this.getData(returnData)//调取接口
};
this.refreshData = this.iniJWT.bind(this);
getSdk().listenCustomEvent('onShow', this.refreshData);
getSdk().listenCustomEvent('dingdingworkbench/request', this.requestParams);
},
didUpdate() {
getLifecycleSdk().didUpdate(this.props.componentName);
},
didUnmount() {
getLifecycleSdk().didUnmount(this.props.componentName);
getSdk().removeCustomEvent('dingdingworkbench/request', this.requestParams);
getSdk().removeCustomEvent('onShow', this.refreshData);
},
methods: {
checkDataReceived() {
if (!this.data.hasReceivedNotification) {
console.log('No notification received, fetching data...');
let componentInitSate = this.data.componentInitSate;
for (let key in componentInitSate) {
if (componentInitSate.hasOwnProperty(key) && !componentInitSate[key]) {
getSdk().triggerCustomEvent(`${key}/init`, true);
}
}
this.timeoutId = setTimeout(this.checkDataReceived, 200); // 每200毫秒检查一次
} else {
clearTimeout(this.timeoutId); // 停止定时器
}
},
async iniJWT(){
let _this = this
// 初始化相关组件接口
let componentInitState = {};
const componentNames = this.props.componentProps.componentNames.split(',');
componentNames.forEach(name => {
componentInitState[name] = false;
});
this.setData({
componentInitState: componentInitState
});
const joinData = JSON.stringify({ apiPath: 'login' });
try {
// 获取JWT
const res = await getSdk().request(this.props.componentProps.gateWayJWT, { joinData }, getSdkParam);
if (res.code === '200') {
this.setData({ ddJWT: res.data });
this.checkDataReceived = this.checkDataReceived.bind(this);
this.checkDataReceived(); // 开始数据请求循环
return Promise.resolve(res.data);
} else {
console.error('Failed to initialize JWT:', res);
}
} catch (error) {
console.error('Error initializing JWT:', error);
}
},
async getData(data){
}
});
// Document组件
Component({
data: {
isInit:false,//是否初始化
requestResultName:'Document/requestResult',// <namespace>/<eventType> 事件名用 / 命名,以防和其他服务商的组件冲突。namespace建议用公司的英文名。 namespace = 组件名称
},
props: {
componentName: '',
componentProps: {},
},
async didMount() {
getLifecycleSdk().didMount(this.props.componentName);
// 统一的初始化方法,监听 Document/init ,触发说明JWT组件初始化完成
this.init = (res) => {
// res 返回值为布尔值,默认为false,
if(res){
//加载页面的相关方法
if(!this.isInit){//防止重复调用初始化
this.isInit = true
this.getListData(0)
}
}
};
// 触发方法 组件名+/init
getSdk().listenCustomEvent('Document/init', this.init);
},
didUpdate() {
getLifecycleSdk().didUpdate(this.props.componentName);
// 业务代码写到下方
},
didUnmount() {
getLifecycleSdk().didUnmount(this.props.componentName);
// 业务代码写到下方
getSdk().removeCustomEvent(this.data.requestResultName, this.requestResult);
getSdk().removeCustomEvent('Document/init', this.init);
},
methods: {
requestJWT(apiPath,param,pluginName){
// 触发 dingdingworkbench/request 方法
let params = {
apiPath,
param,
pluginName
}
getSdk().triggerCustomEvent('dingdingworkbench/request', params);
},
getListData(index){
this.requestJWT(apiPath,params,this.data.requestResultName)
this.requestResult = (res) => {
//返回数据的处理
};
getSdk().listenCustomEvent(this.data.requestResultName, this.requestResult);
},
}
});