Реагирует с помощью обмена данными на основе событий

#reactjs #typescript #visual-studio-code #vscode-extensions

#reactjs #typescript #visual-studio-code #vscode-расширения

Вопрос:

Я пытаюсь использовать React внутри панели веб-просмотра vscode. Я бы считал себя приличным компонентом в 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))
  

Мой мозг пытается определить наилучший способ настройки двусторонней связи.

Например, выполнение запроса из webview для получения данных для ресурса обычно выглядело бы примерно так:

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

но такое ощущение, что я бы изобрел свой собственный протокол (звучит просто, пока вы не начнете рассматривать исключительное поведение, такое как тайм-ауты)!

Комментарии:

1. Отошел, чтобы выпить кофе, и это сработало! При такой настройке Redux работал бы великолепно. Иногда требуется написать диссертацию по stackoverflow, чтобы просто обдумать проблему