-1

I'm working with an API wrapper whose endpoints only accept user ID's when querying - however, there's a single endpoint that lets me search by username (the wrapper for which, searchByUsername, you'll see used below) I wrote the following helper function to convert them before every request fires, to give our users flexibility:

  var convertToID = function (username, callback) {
    searchByUsername(username, function (error, response, body) {
      if (body.users[0]){
        callback(body.users[0].username)
      }
    })
  };

And here's how I'm using it:

  this.relationship = function (user, query, callback) {
    if (isNaN(user)) {
      convertToID(user, function (ID) {
        get('/users/' + ID + '/relationships/?query=' + query, callback);
      })
    } else {
      get('/users/' + user + '/relationships/?query=' + query, callback);
    }
  }

This works fine, but it's obviously sub-optimal to drop this into every one of my wrappers. Coming from a Ruby background, I could condense this to a single line - but the async nature of JS is kind of twisting my brain. What I really want is something comparable to:

var user = isNaN(user) ? convertUsernameToID(user) : user;
get('/users/' + user + '/relationships/?query='+query, callback);

I've explored the other answers (and yes, I know there's a lot of them) re: async JS gotchas, but I must be missing something. In the past on larger projects, I've used the async package but it feels like overkill for this and I'd prefer to actually grok this.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Have you had a look at promises? – Bergi Oct 12 '16 at 16:53
  • Your `convertToID` function doesn't seem to handle errors well (or at all). You really should have a look at promises. – Bergi Oct 12 '16 at 16:58
  • @Bergi Yeah, I've had exposure to bluebird and a little bit of ES6 promises. I actually remember running into a similar issue there, which was that I still couldn't return values from nested functions. So I still couldn't achieve something like the one line solution above - unless I'm just misunderstanding them. Is my head just too stuck in Ruby-land? – commitaphobe Oct 12 '16 at 17:02
  • @Bergi yeah, this was just a rough sketch to flesh it out. It's pretty cringeworthy....I had that thought before I posted it. – commitaphobe Oct 12 '16 at 17:03
  • Using async/await (from ES8) with promises, you can in fact reduce it to a one-liner in JS as well: `async function relationship(user, query) { return get('/users/' + (isNaN(user) ? await convertUsernameToID(user) : user) + '/relationships/?query=' + query); }` – Bergi Oct 12 '16 at 17:12
  • Or, assuming your user IDs are never `0`, you might also want to have a look at [Are there idiomatic ways to express `c1 || c2` in JavaScript when one of the conditions is a promise and the other is not?](http://stackoverflow.com/q/37907983/1048572) – Bergi Oct 12 '16 at 17:14
  • @Bergi awesome. super helpful stuff. thank you! – commitaphobe Oct 12 '16 at 17:30

1 Answers1

0

You can use

function relationship(user, query, callback) {
  if (isNaN(user))
    convertToID(user, getById);
  else
    getById(user);

  function getById(ID) {
    get('/users/' + ID + '/relationships/?query=' + query, callback);
  }
}

If you are using promises, it becomes even simpler, see if-else flow in promise (bluebird).

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375