摘要:坑點(diǎn)一不支持瀏覽器環(huán)境首先你應(yīng)該了解,它的目標(biāo)是將編譯文件所生成的文件夾包含和文件??狱c(diǎn)二所提供的方法只支持回調(diào)函數(shù)以上是官方給出的例子,發(fā)送一個(gè)標(biāo)準(zhǔn)請(qǐng)求。
坑點(diǎn)一:ts-protoc-gen 不支持瀏覽器環(huán)境
首先你應(yīng)該了解 ts-protoc-gen,它的目標(biāo)是將編譯 .proto 文件所生成的文件夾包含 .js 和 .d.ts 文件。
但是...
因?yàn)楫?dāng)我們直接使用如下代碼時(shí):
import { MyMessage } from "../generated/users_pb"; const msg = new MyMessage(); msg.setName("John Doe");
報(bào)錯(cuò):
Uncaught ReferenceError: exports is not defined.
這個(gè)錯(cuò)誤應(yīng)該不陌生,exports 未定義,多見于瀏覽器環(huán)境直接使用 node 環(huán)境代碼,所以我翻看了一下 ts-protoc-gen 的源碼,直到發(fā)現(xiàn)了如下代碼:
printer.printLn(`exports.${service.name} = ${service.name};`);
這里的 exports 就已經(jīng)說明一切了,這個(gè)庫生成的是運(yùn)行在 node 環(huán)境的 CommonJS 規(guī)范代碼,而對(duì)于使用 Webpack4 的 vue project 項(xiàng)目,也并不支持混合使用模塊系統(tǒng),所以目前我想到了個(gè)臨時(shí)解決方案:
// 編譯文件導(dǎo)出方法和類時(shí)強(qiáng)制使用 `es module` // src/service/grpcweb.ts printer.printLn(`var ${service.name} = (function () {`); // line 251 // || // || // / printer.printLn(`export var ${service.name} = (function () {`); printer.printLn(`exports.${service.name} = ${service.name};`); // line 270 // || // || // / // delete .printLn(`function ${service.name}Client(serviceHost, options) {`) // line 286 // || // || // / .printLn(`export function ${service.name}Client(serviceHost, options) {`) printer.printLn(`exports.${service.name}Client = ${service.name}Client;`); // line 304 // || // || // / // delete
這個(gè)方法可以暫時(shí)解決 Uncaught ReferenceError: exports is not defined. 的問題。
坑點(diǎn)二:grpc-web-client 所提供的方法只支持回調(diào)函數(shù)import {grpc} from "grpc-web-client"; // Import code-generated data structures. import {BookService} from "./generated/proto/examplecom/library/book_service_pb_service"; import {GetBookRequest} from "./generated/proto/examplecom/library/book_service_pb"; const getBookRequest = new GetBookRequest(); getBookRequest.setIsbn(60929871); grpc.unary(BookService.GetBook, { request: getBookRequest, host: host, onEnd: res => { const { status, statusMessage, headers, message, trailers } = res; if (status === grpc.Code.OK && message) { console.log("all ok. got book: ", message.toObject()); } } });
以上是官方給出的例子,發(fā)送一個(gè)標(biāo)準(zhǔn)請(qǐng)求??吹?callback 和一堆引入的文件的時(shí)候,我瞬間整個(gè)人就不好了,遂開始琢磨如何二次封裝 gRPC 請(qǐng)求。
首先可以先從 callback 函數(shù)轉(zhuǎn)成 Promise 下手:
// callbackToPromise.js const promiseFunc = new Promise((resolve, reject) => { grpc.unary(BookService.GetBook, { request: getBookRequest, host: host, onEnd: res => { const { status, statusMessage, message } = res; if (status === grpc.Code.OK && message) { resolve(res) } else { reject(res); } } }); }); return promiseFunc;
我們還可以再各這個(gè)請(qǐng)求加上超時(shí)限制(折騰一下準(zhǔn)沒錯(cuò)):
// callbackToPromise.js return utils.fetchTimeout(promiseFunc, 2000).catch(err => { // 設(shè)置 2000 ms 超時(shí) if (err.code === "TIMEOUT") { // 提示超時(shí) } }); // utils.js /** * fetch 超時(shí) helper * * @param {Function} fetchPromise fetch 方法 * @param {Number} timeout 超時(shí)時(shí)間 * @returns Promise */ function fetchTimeout (fetchPromise, timeout) { let abortFunc = null; const abortPromise = new Promise((resolve, reject) => { abortFunc = () => { reject({ code: "TIMEOUT", msg: "TIMEOUT" }); }; }); const abortablePromise = Promise.race([ fetchPromise, abortPromise ]); setTimeout(() => { abortFunc(path); }, timeout); return abortablePromise; }
這樣 callback 函數(shù)專成 Promise 就完成了。
其次我們需要將 grpc-web-client 目標(biāo)文件引入和回調(diào)函數(shù)的封裝分割開來,這樣也有利于之后代碼的維護(hù):
// user.js /** * 根據(jù)用戶 ID 查詢用戶信息 * * @param {String} publicId 用戶 ID */ export function queryUserDetails (publicId) { const queryUserDetailsRequest = new QueryUserDetailsRequest(); queryUserDetailsRequest.setUserPublicId(publicId); const config = { request: queryUserDetailsRequest, headers: { ...headers, ...makeAuthorizationHeader(utils.getToken()) } }; return createRequest(Dashboard.QueryUserDetails, config, transformQueryUserDetailsValue); }
// api.config.js /** * 創(chuàng)建請(qǐng)求 * * @param {Object} service service function * @param {Object} config 配置項(xiàng) * @param {Function} transformValue 響應(yīng)數(shù)據(jù)體轉(zhuǎn)換 * @returns Promise */ export function createRequest (service, config, transformValue) { const promiseFunc = new Promise((resolve, reject) => { ProgressBar.start(); grpc.unary(service, { request: config.request, host: DASHBOARD_API, metadata: new grpc.Metadata(config.headers), onEnd: (res) => { const { status, statusMessage, message } = res; if (status === grpc.Code.OK && message) { ProgressBar.finish(); resolve((transformValue && transformValue(message.toObject())) || message.toObject()); // 在這里我們可以運(yùn)行數(shù)據(jù)轉(zhuǎn)化函數(shù) } else if (status === grpc.Code.Unauthenticated) { ProgressBar.fatal(); errorHandler.showNotice(grpc.Code[status], statusMessage); router.push({ name: "unauthenticated", path: "/403" }); reject(res); } else { ProgressBar.fatal(); errorHandler.showNotice(grpc.Code[status], statusMessage); reject(res); } } }); }); return utils.fetchTimeout(promiseFunc, `${service.service.serviceName}.${service.methodName}`, TIMEOUT).catch(err => { if (err.code === "TIMEOUT") { const { code, msg } = err; ProgressBar.fatal(); errorHandler.showNotice(code, msg); } }); }
代碼很簡單,經(jīng)過以上兩步驟,我們就可以如下輕松加愉快的去請(qǐng)求數(shù)據(jù)了:
import { queryUserDetails } from "@/api/user"; queryUserDetails(publicId) .then(res => console.log(res)) .catch(res => console.log(res));
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108675.html
摘要:為了解決這一系列問題,微博從年開發(fā)了語言的框架,并基于此完成了服務(wù)化改造。這些經(jīng)歷之下微博也積累了一套服務(wù)治理型的服務(wù)化體系。的版,所要解決的是微博平臺(tái)內(nèi)部服務(wù)之間的調(diào)用,因此協(xié)議時(shí),其實(shí)并沒有考慮到跨語言的問題,用的是對(duì)比較友好的。 showImg(https://segmentfault.com/img/remote/1460000012601596?w=1080&h=606); ...
摘要:帶入讓你的服務(wù)同時(shí)提供接口原文地址帶入讓你的服務(wù)同時(shí)提供接口項(xiàng)目地址前言接口需要提供給其他業(yè)務(wù)組訪問,但是協(xié)議不同無法內(nèi)調(diào),對(duì)方問能否走接口,怎么辦微信公眾號(hào)小程序等第三方回調(diào)接口只支持接口,怎么辦我相信你在實(shí)際工作中都會(huì)遇到如上問題,在中 帶入gRPC:讓你的服務(wù)同時(shí)提供 HTTP 接口 原文地址:帶入gRPC:讓你的服務(wù)同時(shí)提供 HTTP 接口項(xiàng)目地址:https://github...
摘要:,托管于騰訊云容器平臺(tái)容器編排工具。適配我們目前的服務(wù)部署在騰訊云托管,節(jié)點(diǎn)使用核的網(wǎng)絡(luò)增強(qiáng)型機(jī)器,所有的后端服務(wù)都以部署,集群外部署高可用支持集群內(nèi)服務(wù)發(fā)現(xiàn),數(shù)據(jù)庫以為主,消息隊(duì)列采用。 距離2017年的見聞技術(shù)架構(gòu)調(diào)整接近2年,隨著業(yè)務(wù)線的發(fā)展,見聞技術(shù)部的項(xiàng)目數(shù)量、項(xiàng)目架構(gòu)類型、基礎(chǔ)設(shè)施規(guī)模、服務(wù)變更頻率都在不斷地增長,帶給SRE的挑戰(zhàn)是如何能更快地助力于開發(fā)人員更快更穩(wěn)定地部署...
摘要:原文地址能不能不用證書過去為什么不行因?yàn)閮H支持標(biāo)識(shí),而標(biāo)識(shí)必須使用傳輸層安全性的協(xié)議,此標(biāo)識(shí)符用于應(yīng)用層協(xié)議協(xié)商字段以及識(shí)別。 如果你以前有涉獵過 gRPC+gRPC Gateway 這兩個(gè)組件,你肯定會(huì)遇到這個(gè)問題,就是 為什么非得開 TLS,才能夠?qū)崿F(xiàn)同端口雙流量,能不能不開? 又或是 我不想用證書就實(shí)現(xiàn)這些功能,行不行?。我被無數(shù)的人問過無數(shù)次這些問題,也說服過很多人,但說服歸說...
閱讀 1430·2021-11-15 11:38
閱讀 3580·2021-11-09 09:47
閱讀 1979·2021-09-27 13:36
閱讀 3226·2021-09-22 15:17
閱讀 2563·2021-09-13 10:27
閱讀 2874·2019-08-30 15:44
閱讀 1189·2019-08-27 10:53
閱讀 2718·2019-08-26 14:00