实战CloudIDE插件开发-前后端方法互相调用
通过实战CloudIDE插件开发-调试代码我们详细介绍了插件代码的调试方法,今天我们将用一个简单的功能示例继续深入到插件开发的细节。本次插件代码项目是通过CloudIDE的新建项目创建的Generic类型插件,就是具备前端独立页面和IDE后端运行时的插件,具体的创建步骤可以参考实战CloudIDE插件开发-快速上手,对于Backend类型的纯后端插件,可以使用CloudIDE已有的界面扩展点来实现前端功能,具体可以参考我们的API文档,由于Generic类型的插件本身包含后端能力,后续的教程中将不再对纯后端的插件进行过多介绍。
准备工作
- 已经创建并处于运行状态的CloudIDE实例,CloudIDE创建方法可以参考《5分钟创建并启动IDE实例》
- 本次插件示例代码:https://github.com/HuaweiIDE/cloudide-example-expose-api.git,可以通过文件->导入项目将代码导入到CloudIDE中。
- 新建终端并执行npm i安装依赖。
后端调用前端
插件目录的详细介绍可以参考 《Directory Structures of Plugin Project》
在前端定义暴露给后端的的方法。
打开src/browser/frontend.ts文件,我们可以看到Frontend类继承自AbstractFrontend,默认需要实现init(), run(), stop()这三个方法,另外我们自定义了一个myApi(message: string)方法,如果我们想把这个运行在浏览器中的myApi方法暴露给后端去调用,我们只需要在函数上添加@expose('function_id')修饰器,注意多个expose修饰器中的function_id不要重复使用
import { LogLevel, WebviewOptions } from '@cloudide/core/lib/common/plugin-common';
import { PluginPage, AbstractFrontend } from '@cloudide/core/lib/browser/plugin-api';
import { exposable, expose } from '@cloudide/messaging';
/**
* Adding your fronted api in this class
* Using '@expose' to expose your function to backend
*/
@exposable
class Frontend extends AbstractFrontend {
/**
* function call to the frontend will wait until init() to be resolved
*/
async init(): Promise<void> {
}
/**
* Entry of your plugin frontend
* In this function your can call function exposed by backend
*/
run(): void {
const myViewOptions: WebviewOptions = {
viewType: 'my-webview',
title: '%plugin.dynamicview.title%',
targetArea: 'main',
iconPath: 'resources/icons/plugin.svg',
viewUrl: 'local:resources/page/dynamic-webview.ejs',
preserveFocus: true,
templateEngine: 'ejs'
};
this.plugin.createDynamicWebview(myViewOptions, true);
document.getElementById('call-print-on-dynamic-webview')?.addEventListener('click', evt => {
//call function exposed on dynamic webview
this.plugin.call('my-webview::myplugin.dynamic.page.print', 'param of function call from plugin main page');
});
document.getElementById('call-createNewFile-on-backend')?.addEventListener('click', evt => {
//call function exposed on backend
this.plugin.call('backend::createNewFile', 'untitled.txt').then((filePath) => {
this.plugin.call('cloudide.window.showInformationMessage', `${filePath} created.`);
});
});
}
stop(): void {
}
/**
* this function can be called from plugin backend as below:
* @example
* ```
* plugin.call('myplugin.page.myApi', 'this is a function call from backend').then(ret => {
* console.log(ret);
* });
*
* ```
*/
@expose('myplugin.page.myApi')
public myApi(message: string) {
const messageDom = document.createElement('div');
messageDom.append(document.createTextNode(`myApi called, param: ${message}`));
document.body.appendChild(messageDom);
}
}
document.addEventListener('DOMContentLoaded', function() {
PluginPage.create([Frontend]);
});
在后端调用前端暴露的方法
打开src/node目录下的backend.ts,我们可以看到Backend类继承自AbstractBacend,默认需要实现init(), run(), stop()这三个方法,我们可以在run()方法中通过this.plugin.call()调用在前端定义的myAPI方法并获取到返回值。
import * as cloudide from '@cloudide/plugin';
import { exposable, expose } from '@cloudide/messaging';
import { LogLevel } from '@cloudide/core/lib/common/plugin-common';
import { AbstractBackend } from '@cloudide/core/lib/node/plugin-api';
/**
* Add your backend api in this class
* Using '@expose' to expose your function to frontend
*/
@exposable
export class Backend extends AbstractBackend {
/**
* function call to the backend will wait until init() to be resolved
*/
async init(): Promise<void> {
}
/**
* Entry of your plugin backend
* In this function you can call function exposed by frontend
*/
public async run(): Promise<void> {
const retValue = await this.plugin.call('myplugin.page.myApi', 'this is a function call from backend');
this.plugin.log(LogLevel.INFO, retValue);
}
public stop(): void {
}
/**
* this function can be called from plugin frontend as below:
* @example
* ```
* plugin.call('your_backend_function_identifier', 'world').then(ret => {
* console.log(ret);
* });
*
* ```
*/
@expose('createNewFile')
public async createNewFile(name: string) {
const edit = new cloudide.WorkspaceEdit();
let absPath = name;
if (cloudide.workspace.workspaceFolders) {
const filePath = cloudide.Uri.file(`${cloudide.workspace.workspaceFolders[0].uri.fsPath}/${name}`);
edit.createFile(filePath);
cloudide.workspace.applyEdit(edit);
absPath = filePath.path;
}
return absPath;
}
}
同样,我们可以在后端定义自己的方法并将方法暴露给前端调用,大家可以运行样例插件的代码测试下效果,也可以尝试自己添加想要的方法实现前后端的调用。插件调试运行可以参考《实战CloudIDE插件开发-调试代码》
- 点赞
- 收藏
- 关注作者
评论(0)