Blazor嵌入Teams应用:JS与JS互操作上下文不共享问题
Blazor Teams应用SDK初始化后仍提示未初始化的解决方案
问题背景
我开发嵌入Microsoft Teams的Blazor应用时,使用Teams JS SDK v2.5.0,通过IJSRuntime从C#调用SDK接口。按要求必须先调用microsoftTeams.app.initialize()完成初始化,才能使用其他SDK功能。
为了在JS互操作可用前和Teams交互,我在页面加载时运行Init.js执行初始化和相关操作。但后续通过Blazor的JS互操作调用SDK时,依然抛出错误:
internalAPIs.ts:28 Uncaught (in promise) Error: The library has not yet been initialized
虽然我保存了初始化的Promise,且开发者工具显示该Promise已处于完成状态,但问题依旧。重复调用初始化能临时解决,但会引发其他未知问题。
相关代码如下:
Init.js
let teamsInitPromise; teamsInitPromise = microsoftTeams.app.initialize(); teamsInitPromise.then(() => { microsoftTeams.app.getContext().then((context) => { // do stuff }); });
interop.razor
await MicrosoftTeams.InitializeAsync(); var context = await MicrosoftTeams.GetTeamsContextAsync(); culture = context.App.Locale;
interop.js
export function getContextAsync() { let scopedPromise = teamsInitPromise; // Promise state "Fulfulled" is shown in developer tools return new Promise((resolve, reject) => { try { microsoftTeams.app.getContext().then((context) => { resolve(context); }); } catch (e) { reject(e); } }); }
问题诊断
- SDK实例不共享:页面加载时
Init.js使用的是全局microsoftTeams实例,但Blazor互操作的interop.js可能因模块加载方式,使用了另一个独立的SDK实例,导致初始化状态无法同步。 - 未显式等待初始化完成:即使初始化Promise已完成,互操作函数中没有显式await该Promise就调用SDK API,可能在渲染时序异常时出现状态不一致。
解决方案
1. 全局共享初始化Promise
修改Init.js,将初始化Promise挂载到全局window对象,确保所有JS文件都能访问同一个初始化状态:
// 将初始化Promise挂载到全局,避免作用域隔离问题 window.teamsInitPromise = microsoftTeams.app.initialize(); window.teamsInitPromise.then(() => { microsoftTeams.app.getContext().then((context) => { // 执行初始化后的操作 }); });
2. 修改互操作函数,等待初始化完成
更新interop.js,确保调用SDK API前等待全局初始化Promise完成:
export function getContextAsync() { // 显式等待初始化完成,即使Promise已完成,await也会直接返回结果 return window.teamsInitPromise.then(() => { return microsoftTeams.app.getContext(); }).catch(err => { throw err; }); } // 添加等待初始化的辅助函数,供Blazor调用 export function waitForTeamsInit() { return window.teamsInitPromise; }
3. 调整Blazor代码,避免重复初始化
移除Blazor中重复调用InitializeAsync的代码,改为等待全局初始化完成后再获取上下文:
// 等待全局的SDK初始化完成 await MicrosoftTeams.WaitForTeamsInitAsync(); // 此时SDK已初始化,可安全调用API var context = await MicrosoftTeams.GetTeamsContextAsync(); culture = context.App.Locale;
4. 确保SDK只加载一次
检查index.html,确保Teams SDK仅通过<script>标签引入一次,避免重复加载导致多实例:
<script src="https://unpkg.com/@microsoft/teams-js@2.5.0/dist/MicrosoftTeams.min.js"></script>
可选:延迟加载Blazor(确保初始化完成后再渲染)
如果需要严格保证Blazor在SDK初始化完成后再加载,可修改index.html的Blazor加载逻辑:
<script> window.teamsInitPromise = microsoftTeams.app.initialize(); window.teamsInitPromise.then(() => { // 初始化完成后再加载Blazor应用 import('./_framework/blazor.webassembly.js').catch(err => console.error(err)); }); </script>
内容的提问来源于stack exchange,提问作者WerkmanW
相关产品推荐
相关产品推荐

