面试题:实现小程序平台的并发双工Rpc通信题目是这样的:rpc是remoteprocedurecall,远程过程调用,比如一个进程调用另一个进程的方法。很多平台提供的进程间通信机制都是以rpc的形式封装的,比如electron的remote模块。小程序是双线程机制,两个线程之间的通信提供了postMessage和addListener的API。现在在两个线程都将导入的common.js文件中实现rpc方法,以支持并发rpc通信。实现这样的使用效果:constres=awaitrpc('method',params);这道题是有真实应用场景的题,比一些逻辑题、算法题更有趣。实现思路postMessageapi用于在两个线程之间传递消息:在rpc方法中,postMessage用于传递要调用的方法名和参数。当addListener中接收到调用时,调用api,然后通过postMessage返回结果或错误我们首先实现rpc方法,通过postMessage传递消息,返回一个promise:functionrpc(method,params){postMessage(JSON.stringify({method,params}));returnnewPromise((resolve,reject)=>{});}这个promise什么时候resolve或者reject?是在addListener收到消息之后。然后先保存,收到消息后调用resolve或者reject。为了支持并发和区分多个调用通道,我们添加了一个id。letid=0;functiongenId(){return++id;}constchannelMap=newMap();functionrpc(method,params){constcurId=genId();postMessage(JSON.stringify({id:curId,method,params}));returnnewPromise((resolve,reject)=>{channelMap.set(curId,{resolve,reject});});这样,每个远程调用请求及其关联的resolve和reject都由id标识。然后需要处理addListener,因为是双工通信,即两次通信都会用到这段代码,所以需要区分是请求还是响应。addListener((message)=>{const{curId,method,params,res}=JSON.parse(message);if(res){//处理响应}else{//处理请求}});处理请求是调用方法,然后返回结果或错误:try{constdata=global[method](...params);postMessage({idres:{data}});}catch(e){postMessage({id,res:{error:e.message}});}处理response就是获取并调用id关联的resolve和reject:const{resolve,reject}=channelMap.get(id);if(res.data){resolve(res.data);}else{reject(res.error);}整个代码是这样的:letid=0;functiongenId(){return++id;}constchannelMap=newMap();functionrpc(方法,参数){constcurId=genId();postMessage(JSON.stringify({id:curId,method,params}));returnnewPromise((resolve,reject)=>{channelMap.set(curId,{resolve,reject});});}addListener((message)=>{const{id,method,params,res}=JSON.parse(message);if(res){const{resolve,reject}=channelMap.get(id);if(res.data){resolve(res.data);}else{reject(res.error);}}else{try{constdata=global[method](...params);postMessage({idres:{data}});}catch(e){postMessage({id,res:{error:e.message}});}}});我们已经达到了初步要求:rpc方法实现,返回一个promise,支持并发调用。两个线程都被引入到这个文件中。其实在支持双工通信的时候主要要注意两点:加一个id来关联请求和响应,这是在socket通信的时候。也经常使用resolve和reject来保存,稍后再调用来取消请求。比如axios中cancelToken的实现,也有很多应用场景都应用了这两点。总结rpc是一种远程过程调用,是跨进程、跨线程等场景下通信的一种常见的封装形式。面试题是小程序平台的双线程场景,在公共文件中实现双工并发rpc通信。思路在文中已经说的很清楚了,主要需要注意的是,promise的resolve和reject可以保存起来,以供后续调用,通过添加id来标识和关联一组requestresponse。
