Búsqueda de sitios web

reactjs - React con una comunicación basada en eventos


Estoy intentando usar React dentro de un panel de vista web de vscode. Me consideraría bastante competente en React, pero estoy acostumbrado a comunicarme con el backend vía HTTP.

En este proyecto, la extensión de vscode es esencialmente el servidor y toda la comunicación debe realizarse enviando eventos entre los dos.

//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))

Mi cerebro está teniendo dificultades para determinar la mejor manera de configurar comunicaciones bidireccionales.

Por ejemplo, hacer una solicitud desde el webview para obtener datos de un recurso normalmente se vería algo así:

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});
       }
    })
}

Pero con la API de Eventos, este enfoque obviamente no funciona...

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

}

Veo cierta discusión sobre registrar listeners en el componentDidMount, pero dado que el evento es un message genérico, entonces prácticamente todos los componentes que se comunican con el servidor van a estar escuchando y luego tendrán que filtrar lo que les importa.

Una idea en este punto es crear una capa de abstracción que permita enviar los mensajes y esperar la respuesta:

//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}});

¡pero esto se siente como si estuviera inventando mi propio protocolo (suena simple hasta que empiezas a considerar comportamientos excepcionales como los tiempos de espera)!