set variable after API call
# 🤝help
p
I am using an API called htmldocs to generate a pdf based on data from the bot. Now I want to provide the user a link, so he can click on it. Unfortunately the variable is not changing at all when I do it from the code cell. The api needs a few seconds to respond and when I do console.log() it logs the url correctly, but it does not save it to my variable. Please help. My code:
Copy code
javascript
const API_KEY_HTMLDOCS = '...'

axios
  .post(
    'https://api.htmldocs.com/v1/api/generate',
    {
      projectId: '...',
      path: 'index.html',
      context: {
        business: 'test'
      }
    },
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + API_KEY_HTMLDOCS
      }
    }
  )
  .then((response) => {
    console.log(response.data.url)
    workflow.pdf_url = response.data.url
  })
  .catch((error) => {
    console.log(error)
  })
b
stupid question but what happens if you add single quotations to the variable
e.g. workflow.pdf_url = 'response.data.url'
p
basically this would save a string, but in this case it is not saving anything. The variable stays empty..
Somehow the bot is proceeding and is not performing variable changes after the response arrives
b
gotcha, but it's printing the correct url to your logs?
p
yes it is
And basically when I do anything that waits variable setting is not possible anymore:
Copy code
javascript
console.log('Start')
setTimeout(function () {
  console.log('Waited for 5 seconds')
  workflow.new_question = 'Test'
}, 5000) // 5000 milliseconds = 5 seconds
new_question will not be changed in this code, but the log prints correctly
interesting: When I do this:
Copy code
javascript
console.log('Start')
setTimeout(function () {
  console.log('Waited for 5 seconds')
  workflow.new_question = 'Test'
  console.log('workflow.new_question after timeout:', workflow.new_question)
}, 5000)
the second log prints "workflow.new....: Test". So the variable is changing locally in the code but not for the bot/workflow. Very weird..
b
oh, strange, thanks for spelling it out like this
p
do you know a fix? Seems for me like a kind of obvious thing, because I assume lots of bot builders need to set a variable based on an API call.. or is there a workaround you could recommend? If you don't know, could you maybe tag someone who could know the solution?
n
I'm having the same problem! Can't set variable from api call. It console logs but doesn't set in workflow.variable
Sample code available and video under my handle tag
I'd suggest using the async "wait" syntax eg Using Axios with async and await The async and await syntax is syntactic sugar around the Promises API. It helps you write cleaner, more readable, and maintainable code. With async and await, your codebase feels synchronous and easier to think about. When using async and await, you invoke axios or one of its request methods inside an asynchronous function, like in the example below: const fetchData = async () => { try { const response = await axios.get("https://api.github.com/users/mapbox"); console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); } catch (error) { // Handle error console.error(error); } }; fetchData(); When using the async and await syntax, it is standard practice to wrap your code in a try-catch block. Doing so will ensure you appropriately handle errors and provide feedback for a better user experience.
That said, I'm still having issues setting workflow variables. With this code. https://discord.com/channels/@me/1151355112468512829/1239333074899046550
Further to this! Not sure if this bug has been resolved https://github.com/botpress/botpress/pull/3295
p
Thanks for the answer, but for me it still does not work. Am I doing something wrong?
Copy code
javascript
const API_KEY_HTMLDOCS = '...'

const generatePDF = async () => {
  try {
    const response = await axios.post(
      'https://api.htmldocs.com/v1/api/generate',
      {
        projectId: '...',
        path: 'index.html',
        context: {
          business: 'test'
        }
      },
      {
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${API_KEY_HTMLDOCS}`
        }
      }
    )

    console.log(response.data.url)
    workflow.pdf_url = response.data.url
  } catch (error) {
    console.error(error)
  }
}

generatePDF()
`
is there maybe a way to wait for the code card to complete before continuing the workflow?
Because I assume it is not settable anymore since the workflow continues and is not waiting for the api fetch to complete
n
There's an alternative wait syntax... Axios is a popular JavaScript library used to make HTTP requests, and "waiting" in this context usually refers to handling asynchronous operations. When you make a request with Axios, it returns a promise. This promise allows you to "wait" for the request to complete before proceeding with other code, which is crucial for getting data from a server before you try to use that data in your application. Here are a couple of ways to handle the waiting in Axios: 1. **Using
.then()
and
.catch()
methods**: After sending a request, you can use these methods to handle the response and errors respectively. The code execution inside these methods will only run after the Axios promise resolves, ensuring that you have the data you need before it executes.
Copy code
javascript
   axios.get('https://example.com')
       .then(response => {
           console.log('Data:', response.data);
       })
       .catch(error => {
           console.error('Error:', error);
       });
2. **Using async/await**: This is a more modern syntax to handle promises. You can mark a function as
async
, which allows you to use
await
to pause the function’s execution until the promise resolves. This makes your asynchronous code look and behave a little more like synchronous code, which can be easier to understand and manage.
Copy code
javascript
   async function fetchData() {
       try {
           const response = await axios.get('https://example.com');
           console.log('Data:', response.data);
       } catch (error) {
           console.error('Error:', error);
       }
   }
   fetchData();
In both cases, the code execution "waits" at the point of the request until the server responds, and then it proceeds with the returned data or handles any errors. This waiting is crucial for working with any asynchronous API calls in JavaScript.
p
but haven't I used the second option in my code? It looks correct to me.
n
Need one the BP dev team to verify as although it should, it appears not to as when uses to retrieve api data, it doesn't set workflow.variables!
p
you know anyone who could take a look over it?
n
Sadly no, just hoping someone will be proactive from the team whilst everyone gets over GPT 4o #DEV #Urgent
@bumpy-butcher-41910
p
also hope so.. Other ideas that would work fow me would be: - directly print the url to the chat once it is loaded (don't know, how..) - download the pdf from the link and attach it to an email which is sent via sendgrid api (already setup sendgrid, but I am too stupid to download the file and attach it as a pdf...)
I will try it and maybe I find a way to fix something
@nice-airplane-37559 you know if there is a way to download some libs for execute code via npm? Something like puppeteer would help me a lot
n
Reading your requirements, why don't you just email the user the pdf, using make or Zapier
p
I have done it like this as a workaround, but I think that it still would be nice to have the possibility of changing the variables from execute code cards after an API Call
7 Views