1

I am trying to further extend the telegram-rocket.chat bridge and need to call some apis for that. For this, rocket.chat exposes a Meteor.js wrapper called HTTP.

This code snippet is an outgoing-hook that processes a message sent by a user, lets me transform the message and pass along the altered text.

The prepare_outgoing_request({request}) gets called by the rocket.chat hook and I'd like to call an API within it that resolves emoji codes to the actual emoji-character: ":see_no_evil: to "

/** Global Helpers
 *
 * console - A normal console instance
 * _       - An underscore instance
 * s       - An underscore string instance
 * HTTP    - The Meteor HTTP object to do sync http calls
 *           https://docs.meteor.com/api/http.html
 */


class Script {
    request_emojitext(emoji_code) {
       console.log(`called: request_emojitext('${emoji_code}')`);
       const url = `https://www.emojidex.com/api/v1/emoji/${emoji_code}`;
  
       const response = HTTP.call('GET', url);

       console.log(`Emoji Response: ${response.constructor.name} => ${JSON.stringify(response)}`);
      // Emoji Response: Object => {"error":{}}             
       return response;
    }
  
    /**
     request.params            {object}
      request.method            {string}
     request.url               {string}
     request.headers           {object}
     */
    prepare_outgoing_request({ request }) {
       const emojiResponse = this.request_emojitext('see_no_evil');
       const emojiCharacter = emojiResponse.content.emoji;
        
        return {
          // https://core.telegram.org/bots/api
          url: `${request.url}&text=${emojiCharacter}`,
          method: 'GET'
        };
    }
}

The Meteor documentation states that:

// Asynchronous call
Meteor.call('foo', 1, 2, (error, result) => { ... });

// Synchronous call
const result = Meteor.call('foo', 1, 2);

/*
On the client, if you do not pass a callback and you are not 
inside a stub, call will return undefined, and you will have 
no way to get the return value of the method. That is because
the client doesn’t have fibers, so there is not actually any 
way it can block on the remote execution of a method.
*/

I am unsure on how to procede here as I'm not entirely comfortable with asynchronous programming yet. How would I block until the result is actually available, or is there a different way of doing this that I am completely missing?

Michael Kargl
  • 622
  • 9
  • 21

2 Answers2

1

Like the documentation says, there is no way to block on the client -- browsers simply don't implement any mechanism for that. So the question is what it is that makes it difficult for you to deal with the delay on the client until the callback is called. The typically pattern, of course, is to switch the client into some sort of "waiting" state when the call is made (e.g., show a spinner), and then update the page with the result when the callback fires (and hide the spinner).

Christian Fritz
  • 15,980
  • 3
  • 38
  • 58
  • I was afraid of that. It is an integration of rocket.chat so I don't have any control over the client. Rocket.chats limitation of holds me back from doing continuations. What confuses me is that they provide access to, a seemingly unusable, Meteor library to do WebRequests. There needs to be a reason for it to be exposed. But maybe thats a question better asked on github. Thanks for the quick answer. – Michael Kargl Nov 05 '18 at 11:18
1

I found the problem through looking at the implementation of the HTTP variable (PR #5876). Plus a feature request for asynchronous calls has been opened (Issue #4775).

const response = HTTP('GET', 'https://www.emojidex.com/api/v1/emoji/sweat_smile');

This executes the API call synchronously and returns a result object:

{
  "result": {
    "statusCode": 200,
    "headers": {
      // ...
    },
    "data": {
      "code": "sweat smile",
      "moji": "",
      // ...
    }
  }
}

If you want to see the full code you can check it out on Git

Michael Kargl
  • 622
  • 9
  • 21