2

So this is the code for yelp-fusion node.js API used in dialogflow v2.

Problem: agent.add(response.jsonBody.businesses[0].name); which should make the bot say the name of the business doesnt actually run even though the code is there.

From research, other answers mentioned the need to use the fat arrow => in this javascript promises.

However, it is already being used. The code inside .then() isnt running, except for console.log, which does run.

Could anyone advice on what i can do to run methods inside javascript promises? Or other alternatives? Much appreciated. Thanks!

client below is the yelp API client.

agent is a webhookclient in dialogflow. agent.add() works when executed outside of this code below.

    client.search({
      term:'Four Barrel Coffee',
      location: 'san francisco, ca'
    }).then(response => {
      //res = response.jsonBody.businesses[0].name; //*not assigned!
      console.log(response.jsonBody.businesses[0].name); 
      agent.add(response.jsonBody.businesses[0].name); //*nothing!
    }).catch(e => {
      console.log(e);
    });
brooksrelyt
  • 3,482
  • 4
  • 22
  • 42
vade
  • 103
  • 1
  • 2
  • 8
  • what is agent.add? is it async? can you post some context. – Aritra Chakraborty Aug 05 '18 at 14:26
  • @AritraChakraborty Added more information about what is agent - agent.add is a method in dialogflow that asks the bot to say something. It works when ran outside the above code. – vade Aug 05 '18 at 14:32
  • So that commented-out `console.log(response.jsonBody.businesses[0].name)` actually executes (when it's un-commented)? What does it log to the console? Make sure it's not logging an object that is populated later. Try `console.log(\`Name: ${response.jsonBody.businesses[0].name}\`)` – Phil Aug 06 '18 at 00:11
  • Perhaps try a different SDK such as this one linked from the official Yelp Fusion repo ~ https://github.com/olalonde/node-yelp – Phil Aug 06 '18 at 00:22
  • @Phil Thanks for the suggestion. Will do! – vade Aug 06 '18 at 10:00

1 Answers1

1

You have half the solution. It isn't so much to use the fat-arrow, it is that you're dealing with asynchronous functions (the client.search call) and that when you use async functions with the dialogflow-fulfillment library, you need to use Promises.

Specifically - you need to return a Promise so the calling function knows that it has to wait for all the then() clauses to finish in order to send the reply.

You don't show your entire function, but you can probably do it by adding a few return statements. Possibly something like this:

return client.search({
  term:'Four Barrel Coffee',
  location: 'san francisco, ca'
}).then(response => {
  return agent.add(response.jsonBody.businesses[0].name);
}).catch(e => {
  console.log(e);
  return Promise.reject( e );
});
Prisoner
  • 48,391
  • 6
  • 48
  • 97
  • I don't think this is the issue. Nothing in OP's question suggests they're relying on the return value of the `client.search()` call. – Phil Aug 06 '18 at 00:12
  • I'm not sure why you say that @Phil. The OP has a `then()` block which gets the result of the `client.search()` in `response`. They they use `response` in the call to `agent.add()`. They said the `console.log()` worked, which suggests that the `agent.add()` did not. `agent.add()` is part of the Dialogflow library and returns results to the user, but relies on a Promise being returned if there are async functions involved. I don't know the `client.search()` function, but it sure looks like it is async. There is no evidence that a Promise is returned in the OP's sample code. – Prisoner Aug 06 '18 at 00:28
  • Wouldn't `agent.add()` just execute when called though? What difference does it make if its return value is returned / resolved in an outer promise or not? I'm not familiar with _DialogFlow_ so happy to be shown where my assumptions might be wrong – Phil Aug 06 '18 at 00:32
  • 1
    Unfortunately not. If the response has already been sent to the user (which would be done if the function exited without returning a Promise), then you're `add()`ing to a message that has already been sent. It is like trying to send an HTTP response after the entire response was already sent to the user and the connection closed. (Actually... it isn't like that... it is that.) – Prisoner Aug 06 '18 at 00:37
  • Great! Thanks for the extra information. Hope this solved OP's problem – Phil Aug 06 '18 at 00:42
  • Thanks for your help! All of you! It was the outer return client.search() that actually made the bot talk, and it is still possible without the inner return (return agent.add()). However, i cannot assign client.search() to a variable and return it thereafter. I had to return it then and there :( Any idea to save the returned value for manipulation if needed thereafter? If not, i guess creating one function for each query / search wont hurt, and calling the various functions all together and manipulate them in a "master" function. – vade Aug 06 '18 at 09:51
  • Read up on how Promises work. The call to `client.search()` technically doesn't return a value - it returns a Promise that eventually resolves to a value that you evaluate in the `.then()` function of the Promise. If you want to create a function that does the search and your calling functions will all determine the output text, then you need to have the function with the search return the promise, evaluate it in a `then`, as above, and return whatever that call/evaluation is (which will be a Promise). (Ask this as a new question if you need clarification - solid examples work better.) – Prisoner Aug 06 '18 at 10:20