通过基于事件的交流做出反应

时间:2019-03-27 17:05:00

标签: reactjs typescript vscode-extensions

我正在尝试在vscode webview panel中使用React。我认为自己是React的重要组成部分,但我习惯于通过http与后端进行通信。

在此项目中,vscode扩展实质上是服务器,并且所有通信都必须通过在两者之间发送事件来完成。

//vscode extension (server)

//send message to react app
panel.webview.postMessage({ command: 'refactor' });
//receive messages from react app
panel.webview.onDidReceiveMessage(message => console.log(message))
//webview (react app)

//send message to extension
const vscode = acquireVsCodeApi();
vscode.postMessage({command: 'hello', text: 'world'});
//receive messages from extension
window.addEventListener('message', event => console.log(event))

我的大脑正在努力确定建立双向通讯的最佳方法。

例如,从Web视图发出请求以获取资源数据通常看起来像这样:

public refresh = () => {
    this.setState({loading: true}, async () => {
       try{
         const item = await (await fetch('api/items/3')).json();
         this.setState({item});
       }catch(e){
         this.setState({loading: false, err: e});
       }
    })
}

但是使用Event API时,这种方法显然行不通...

public refresh = () => {
   // could register a listener before sending and deactivate it after, but that seems wrong!
   vscode.postMessage({command: 'getItems', id: '3'});

}

我看到了一些有关在componentDidMount中注册侦听器的讨论,但是由于该事件是通用的message,因此与服务器通信的几乎每个组件都将被侦听,然后不得不过滤掉它在乎什么。

这时的一个想法是创建一个抽象层,该层允许发送消息并等待响应:

//track requests and wait for a response
const PENDING_REQUESTS = {};
function vscodeFetch(payload: any){

    return new Promise((resolve, reject) => {
        let reqId = crypto.getRandomValues(new Uint32Array(4)).join('-');
        vscode.postMessage({reqId, payload);
        PENDING_REQUESTS[reqId] = {resolve, reject};
    });

 }

 //handle update resolve/reject promises on response
 window.addEventListener('message', event => {
    const message = event.data;
    if(message.reqId){
        let promise = PENDING_REQUESTS[message.reqId];
        delete PENDING_REQUESTS[message.reqId];
        if(message.success){
            p.resolve(message.resp);
        }else{
            p.reject(message.err);
        }
    }
 });



let items = await vscodeFetch({command: 'getItems', data: {id: 3}});

但这有点像我要发明自己的协议(听起来很简单,直到您开始考虑超时等异常行为为止!)

0 个答案:

没有答案