Grpc-web: How to return grpc message results

Created on 17 Nov 2017  路  2Comments  路  Source: improbable-eng/grpc-web

I'm trying to create an Angular 4 webapp that displays the data retrieved in the grpc call. But, I'm having a heck of a time figuring out how to do it -- likely because I'm not very familiar with typescript/js. I'd appreciate a pointer on how I can get this to work.

Given the getBook example:

function getBook() {
  const getBookRequest = new GetBookRequest();
  getBookRequest.setIsbn(60929871);
  grpc.unary(BookService.GetBook, {
    request: getBookRequest,
    host: host,
    onEnd: res => {
      const { status, statusMessage, headers, message, trailers } = res;
      console.log("getBook.onEnd.status", status, statusMessage);
      console.log("getBook.onEnd.headers", headers);
      if (status === Code.OK && message) {
        console.log("getBook.onEnd.message", message.toObject());
        //document.write(message.toString());
      }
      console.log("getBook.onEnd.trailers", trailers);
      queryBooks();
    }
  });
}

I can see the json object being displayed in the console log, but I can't figure out how to return that data so I can bind it to an Angular component and display it in the browser. I've tried something like this:

function getBook(): object {
  var result: object = {};
  const getBookRequest = new GetBookRequest();
  getBookRequest.setIsbn(60929871);
  grpc.unary(BookService.GetBook, {
    request: getBookRequest,
    host: host,
    onEnd: res => {
      const { status, statusMessage, headers, message, trailers } = res;
      console.log("getBook.onEnd.status", status, statusMessage);
      console.log("getBook.onEnd.headers", headers);
      if (status === Code.OK && message) {
        console.log("getBook.onEnd.message", message.toObject());
        result = message.toObject()
      }
      console.log("getBook.onEnd.trailers", trailers);
      queryBooks();
    }
  });
  return result
}

But, result is always empty, which I gather is because the grpc.unary call is asynchronous. I've also tried creating an Observable, but I still ended up with an empty value.

I've been trying to figure this out for three days and I am at a loss. Any pointers on how to return the retrieved data so I can bind it in my browser would be much appreciated.

Most helpful comment

The result is empty because it returns a Promise, not the actual result. You can try something like this.

public getBook(): Promise<any> {
  const getBookRequest = new GetBookRequest();
  getBookRequest.setIsbn(60929871);
  const requestPromise = new Promise<any>((resolve, reject) => {
            grpc.unary(BookService.GetBook, {
                request: getBookRequest,
                host: host,
                onEnd: (res) => {
                    const {status, statusMessage, headers, message, trailers} = res;
                    if (status === Code.OK && message) {
                         console.log("getBook.onEnd.message", message.toObject());
                         resolve(message.toObject());
                     }
                },
            });
        });
  return requestPromise;
}

If you are calling getBook from another function, you can get result like this way

public async someFunction(): Promise<any> {
  book: any = await getBook();
  // do binding here 
  ...
}

Or

getBook().then(function(result) {
   book: any = result;
   // do binding here
    ...
});

All 2 comments

The result is empty because it returns a Promise, not the actual result. You can try something like this.

public getBook(): Promise<any> {
  const getBookRequest = new GetBookRequest();
  getBookRequest.setIsbn(60929871);
  const requestPromise = new Promise<any>((resolve, reject) => {
            grpc.unary(BookService.GetBook, {
                request: getBookRequest,
                host: host,
                onEnd: (res) => {
                    const {status, statusMessage, headers, message, trailers} = res;
                    if (status === Code.OK && message) {
                         console.log("getBook.onEnd.message", message.toObject());
                         resolve(message.toObject());
                     }
                },
            });
        });
  return requestPromise;
}

If you are calling getBook from another function, you can get result like this way

public async someFunction(): Promise<any> {
  book: any = await getBook();
  // do binding here 
  ...
}

Or

getBook().then(function(result) {
   book: any = result;
   // do binding here
    ...
});

Thanks a lot @joenayjoe. That got me past that sticking point. I'm rendering my results on a browser now.

Was this page helpful?
0 / 5 - 0 ratings