asyncfunction,asyncfunction flink
qiankun怎么添加仅子应用可见的全局变量
1.安装qiankun
qiankun的官网 qiankun - qiankun
安装过程
$ yarn add qiankun # or npm i qiankun -S
主应用安装,子应用不需要安装;
2.主应用 qiankun 配置内容;
vue - template - admin 作为本次记录的主体;
新建 micro.js
在一下代码段中,将按照qiankun的配置模式,为主应用配置加载的主应用内容;
/**
* qiankun 模式
* 子系统构建主控文件
* date:2021-11-26
* author:yangming
* description:子系统挂在,并通过主控文件,将子系统挂在进入主系统
*/
import axios from 'axios'
import { registerMicroApps, start, initGlobalState } from 'qiankun'
import store from '@/store/index'
// #region 加载外部配置文件
/**
* 用于配置,项目读取的自定义配置内容
* @returns 自定义配置内容读取
*/
async function getConfig() {
var config = {}
const localPath = process.env.NODE_ENV === 'development' ? '' : ''
if (process.env.NODE_ENV === 'development') {
// config = require(`../../../${localPath}server.config.json`)
config = await axios.get(`../../../server.config.json`)
} else {
config = await axios.get(`../../${localPath}/server.config.json`)
}
// console.log(config)
return config
}
// #endregion
// #region 全局监控配置
var actions = null
function GlobalState(status) {
if (!actions) {
actions = initGlobalState(status)
actions.onGlobalStateChange(
(value, prev) = {
// console.log(`[主应用接收到值变化 - ${actions}]:`, value, prev)
}
)
} else {
actions.setGlobalState(status)
}
}
// #endregion
/**
* 用户登录后,装载子系统
* @param {*} token
*/
async function LoadingMicro() {
// console.log('开始加载子系统')
await getConfig().then(res = {
var apps = res.data.MICRO_APPS
if (apps == undefined apps.length 1) { return }
/**
* @description: 乾坤注册子应用
* @param1 子应用配置
* @param2 打开子应用时候触发的生命周期
*/
registerMicroApps(apps, {
beforeLoad: [
function (app) {
// console.log('[主应用] before load %c%s', 'color: green;', apps.length)
}
],
beforeMount: [
function (app) {
var initState = {
userId: store.getters.userId,
token: store.getters.token,
route: store.getters.routeList.filter(x = x.meta.code == app.name),
code: app.name,
role: []
}
// 信息变更:全局通知
GlobalState(initState)
// console.log('[主应用] before mount %c%s', 'color: red;', app.name)
}
],
afterMount: [
function (app) {
// console.log('[主应用] afterMount mount %c%s', 'color: green;', app.name)
}
],
afterUnmount: [
function (app) {
// console.log('[主应用] after unmount %c%s', 'color: green;', app.name)
}
]
})
start()
})
}
export default LoadingMicro
并在Layout Index.vue中的create 时 LoadingMicro这个方法,用于在客户端启动页面时,装载子应用;
server.config.json是外部配置文件,用于在系统部署后,可通过修改Json的内容,重新配置主应用的加载内容,可根据自己实际情况进行配置注册;
{
"BASE_URL":"",
"MICRO_APPS":[
{
"name": "EMS",
"entry": "//localhost:20009",
"container": "#ChildSystem",
"activeRule": "#/ems-micro",
"props": {
"code": "EMS",
"name": "EMS - Test"
}
}
]
}
完成以上步骤之后,基本上已经完成了主应用的qiankun配置;
注意:由于子应用启动的时候,需要和主应用保持相对信息一致(token、时间戳),所以,在主应用的qiankun启动时,需要对全局状态进行广播,就需要在beforeMount时,更新全局通知的一致性信息,包括了token、userid等内容;(尤其,在主应用退出登录后,重新登录时,同步token,userid,未避免token不一致,导致的子应用死循环,验证token);
3.子应用配置
在主应用配置完成后,就要对子应用进行配置,配置过程中,可在子应用的main.js中直接配置,也可以自己建立一个js文件用于管理子应用配置内容;
/**
* 新增:
* 渲染函数
* 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行
*/
function render(props) {
// console.log('子应用render的参数', props)
props.onGlobalStateChange((state, prevState) = {
// console.log('通信状态发生改变:', state, prevState)
store.dispatch('authorization/microRegisterActive', state)
}, true)
// 挂载应用
instance = new Vue({
router,
store,
render: (h) = h(App)
}).$mount('#micro-app')
}
// new Vue({
// el: '#app',
// router,
// store,
// render: h = h(App)
// })
// 新增:用于保存vue实例
let instance = null
// console.log(window.__POWERED_BY_QIANKUN__)
// 新增:动态设置 webpack publicPath,防止资源加载出错
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
/**
* 新增:
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap(props) {
// console.log(props)
// console.log('初始化调用')
}
/**
* 新增:
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props) {
// console.log('触发时调用', props)
render(props)
}
/**
* 新增:
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
store.dispatch('authorization/microUnApp')
// console.log('切出或卸载调用')
instance.$destroy()
instance = null
}
// 新增:独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
我是在main.js中直接进行了配置,因为内容不是很多,而且一旦配置ok,基本上不会出现变更;
请注意在render方法中的 store的 authorization/microRegisterActive 方法
该方法的目的,就是为了接收到全局状态通知的时候,用于新的数据注册控制;
/**
* 注册路由
* @param {*} param0
* @param {*} data
*/
microRegisterActive({ commit }, data) {
commit('setInfo', data)
// 全局变量中如果已经存在router 则不需要再次装载,避免冲突:黄色警告
if (state.route.length === 0) {
var newRouter = microRegisterRouter(data.route, data.code.toLowerCase() + '-micro')
router.addRoutes(newRouter)
commit('setRoute', newRouter)
}
}
这个方法的目的就是为了在子应用的全局变量中注册,主应用的全局通知,并注册从主应用获取的子应用对应的路由信息,并注册进入子应用的router中;
完成这个配置以后,子应用中的全局变量中,就已经有了token、userid、routerArray数据了,那么子应用的相关全局信息已经健全,类似完成了登录工作;
但是,在子应用运行过程中,还需要根据业务的实际情况,对用户的活动状态进行校验时,就需要判定当前用户是否为活动用户;
如果不需要如此业务进行支撑,就需要保证子应用在脱离主应用的情况下,无法独立运行;
因为我们的request的请求过程中,必须要带入token这个头参数,这样才能保证子应用的微服务可以通过与主应用的微服务进行校验通讯,否则访问非法;
同样的,在主应用的全局通讯过程中,还可以将子应用的code传递过来,便于日志记录过程中,区别日志来源是那个子系统。如果,在使用子应用的横向扩展时,也可以根据code进行编号处理,便于区分相关操作的渠道;(这个就不展示了,需要自己实现);
4.部署
在完成以上配置后,主应用和子应用的启动过程和开发过程基本上,就已经满足开发使用了。
然而,在部署过程中,可能就会遇到一些红色问题;
例如:css、js文件找不到。
这个问题,就需要在子应用的vue.config.js中进行配置,主要配置内容就是publicPath的路径变更
publicPath: process.env.NODE_ENV === 'development' ? '/' : '/microApps/ems-micro'
这个配置路径的解释:判断当前是否为开发模式,如果是开发模式,那么publichPath的路径就是‘/’ ,而当前模式不是开发模式时,就需要将publicPath更改为'/microApps/ems-micro'
如此才能让部署过程中,子应用的路径正确;
microApps/ems-micro 是物理路径,也就是在主应用的 dlist 中 创建microApps文件夹,并在 microApps文件夹中创建ems-micro文件夹,用于存放,ems-micro工程的dlist文件;
注意:publicPath的部署路径,必须和文件创建的路劲一致,否则就会报错;
5.前端同一端口部署说明
1.文件夹结构说明
在部署过程中,需要将主应用与子应用使用一个端口的配置如下:
在开发过程中 Entry 可以为localhst:00001这种模式,如果要发布,则要将子应用的路径改为绝对路径。且前后必须,加入 / , 例如:/mes-micro/
"MICRO_APPS":[
{
"name": "MES",
"entry": "/mes-micro/", // 与主应用的文件管理器中的路径一致
"container": "#ChildSystem",
"activeRule": "#/mes-micro",
"props": {
"title":"生产管理系统",
"code": "MES",
"name": "MES - System",
"userId": null,
"token":null,
"route": null
}
}
]
所谓路径一致,就是要在如下模式:
红色框选中,就是子应用的vue发布代码;
2.子应用配置,需要在vue.config.js中配置publicPath
publicPath: process.env.NODE_ENV === 'development' ? '/' : '/mes-micro/',
js回调函数如何实现异步,给一个例子
异步处理不用阻塞来等待处理完成,而是允许后续操作,直至其程序将处理完成,并回调通知此函数
那么在js中有如下几种异步方式:
示例1
var?async=function(callback){
????//read?data
????setTimeout(function(){
????????callback('data');
????},1000);//1秒后回调
};
//使用
async(function(data){
????alert(data);
});
示例2
var?async=function(callback){
????var?xhr=new?XMLHttpRequest();
????xhr.open('get','.',true);
????
????xhr.onreadystatechange=function(){
????????callback(xhr.readyStatus);
????};
????xhr.send();
};
async(function(data){
????alert(data);
});
示例3
var?async=function(callback){
????var?img=new?Image();
????img.onload=img.onerror=function(){
????????callback(img);
????};
????img.src='x.jpg';
};
async(function(data){
????alert(data);
});
求深入浅出讲解VB.NET下利用Async和Await实现异步的方法。
run需要一个action方法。
这个方法用于用后台进程执行占用大量CPU的工作,你的for代码段应该写在里面。
我没用过这个,粗略看了一下资料,实际情况与他的实例不太一样,Dim a As Task(of Boolean)=Await Doo(),直接提示错误,正确用法是去掉await。
解决以上两个问题,测试运行通过。(一个文本框滚数字,另一个打字无压力)
其实你的要求,不需要这么高级。多线程应该可以。
如何使用promise获取异步方法的结果?
async/await机制我也不是太明白,还特意去看了看相关介绍
看后觉得你这段代码很可能问题
let p1 = new Promise(function(resolve,reject){
//调用上传子组件的异步上传文件方法
_this.$refs.multipleUpload.submitUpload()
resolve(true)
})
因为getResult被定义为async异步,其本质会返回一个promise
然后你又在里面new一个Promise,貌似有嵌套了。
直接return上传结果试试
async function getResult() {
let p1 = await _this.$refs.multipleUpload.submitUpload();
console.log(p1);
return p1
}
let result = getResult();
result.then(...);
js async和await的用法
async 是一个修饰符,被它定义的函数会默认的 返回 一个 Promise 的 resolve的值。
因此对 async 函数可以直接进行 then 操作,返回的值即为 then() 方法的传入函数。
await 同 async 一样,作为修饰符,但是它只能放在 async 内部使用。
它是 获取 Promise 中返回的内容, 即这个 Promise 函数中 resolve 或者 reject 的值。
所以,async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。
如下例:
比如说,这样一个场景:等待三个数据结果都返回,计算它们的和
如何理解回调函数的异步执行
异步处理不用阻塞来等待处理完成,而是允许后续操作,直至其程序将处理完成,并回调通知此函数
那么在js中有如下几种异步方式:
示例1
var async=function(callback){
//read data
setTimeout(function(){
callback('data');
},1000);//1秒后回调
};
//使用
async(function(data){
alert(data);
});
示例2
var async=function(callback){
var xhr=new XMLHttpRequest();
xhr.open('get','.',true);
xhr.onreadystatechange=function(){
callback(xhr.readyStatus);
};
xhr.send();
};
async(function(data){
alert(data);
});
示例3
var async=function(callback){
var img=new Image();
img.onload=img.onerror=function(){
callback(img);
};
img.src='x.jpg';
};
async(function(data){
alert(data);
});