实战CloudIDE插件开发-前后端方法互相调用

举报
克劳德爱第一 发表于 2021/01/06 11:23:46 2021/01/06
【摘要】 通过样例插件展示前后端方法的相互调用

通过实战CloudIDE插件开发-调试代码我们详细介绍了插件代码的调试方法,今天我们将用一个简单的功能示例继续深入到插件开发的细节。本次插件代码项目是通过CloudIDE的新建项目创建的Generic类型插件,就是具备前端独立页面和IDE后端运行时的插件,具体的创建步骤可以参考实战CloudIDE插件开发-快速上手,对于Backend类型的纯后端插件,可以使用CloudIDE已有的界面扩展点来实现前端功能,具体可以参考我们的API文档,由于Generic类型的插件本身包含后端能力,后续的教程中将不再对纯后端的插件进行过多介绍。

准备工作

  1. 已经创建并处于运行状态的CloudIDE实例,CloudIDE创建方法可以参考《5分钟创建并启动IDE实例
  2. 本次插件示例代码:https://github.com/HuaweiIDE/cloudide-example-expose-api.git,可以通过文件->导入项目将代码导入到CloudIDE中。import-project.gif
  3. 新建终端并执行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插件开发-调试代码

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。