1

I have an async function that I would like to return a value from and then use.

Within the updatedStyleSheet function, I'd like to return the updated_css so that I can use it somewhere else.

async function updatedStyleSheet() {
  const res = await fetch("./prism.css");
  const orig_css = await res.text();
  let updated_css = orig_css;

  const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/g;
  let cssVars = orig_css.matchAll(regexp);
  cssVars = Array.from(cssVars).flat();

  for (const v of cssVars) {
     updated_css = updated_css.replace(v,   colors[v.slice(6, -1)]);
   };

// return updated_css ?
}

If I call this function, I get a Promise object. Rightfully so, since async functions always return a promise.

Could I return the updated_css within the updatedStyleSheet function and do something like this after?

const newSheet = updatedStyleSheet().then(css => css)

Then use the newSheet variable wherever in my script?

End Goal

Take the updated_css that contains the text contents of my CSS and use it as an href value so the user can download the stylesheet.

Edit

I attempted to add an event handler so that all the selected color values would be saved in the stylesheet once the user saves it, but it doesn't seem to work. I know it is still an issue with my understanding of promises as a whole.

What I did.

const updatedStyleSheet = async () => {
  const res = await fetch("./themes/prism.css");
  const orig_css = await res.text();
  let updated_css = orig_css;

  const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/g;
  let cssVars = orig_css.matchAll(regexp);
  cssVars = Array.from(cssVars).flat();
  console.log(cssVars)

  for await (const variable of cssVars) {
    const trimmedVar = variable.slice(6, -1)
    const styles = getComputedStyle(document.documentElement)
    const value = String(styles.getPropertyValue(`--${trimmedVar}`)).trim()

    updated_css = updated_css.replace(variable, value);
  }
  console.log(updated_css)

  return updated_css
}

const main = async () => {
  const downloadBtn = document.getElementById('download-btn')
  downloadBtn.addEventListener('click', () => {
    const updated_css = updatedStyleSheet()
    downloadBtn.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(updated_css))
    downloadBtn.setAttribute('download', 'prism-theme.css')
  })
}

main()

I can't await the updated_css because it falls into the callback of the click event, which is a new function.

Then I did the following thinking it would work since it was top level.

const downloadBtn = document.getElementById('download-btn')
downloadBtn.addEventListener('click', async () => {
  const updated_css = await updatedStyleSheet()
  downloadBtn.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(updated_css))
  downloadBtn.setAttribute('download', 'prism-theme.css')
})

That gave me the following error TypeError: NetworkError when attempting to fetch resource.

2
  • Yes, css in the then callback would be your returned item but it doesnt return it to the outside you will just get another promise. You cant go from async code and then back to the outside sync code Commented Jan 11, 2020 at 19:02
  • newSheet is again going to be a Promise. As @PatrickEvans said, "You can't go from async code and then back to the outside sync code". However, as you said you want to use it as an href value, you can do that inside .then(). Commented Jan 11, 2020 at 19:07

3 Answers 3

1

Yes. Since you're already using async/await, just create a top level async function, say main, and use the returned updated_css content after awating the promise to resolve:

async main() {
  const updated_css = await updatedStyleSheet()
  // use css as you please
}

// run program
main()

Don't mind the cost of one more function call.

Sign up to request clarification or add additional context in comments.

1 Comment

I've made an edit to my question regarding this answer and adding a click event that doesn't seem to work.
1

I would collapse the promise by using the .then() function EX:

var bar = updatedStyleSheet()
bar.then(updated_css=>{
//logic goes here
});

Comments

0

If you need to wait for an async function to return a value (so that you can use this value afterwards), use the await keyword:

const newSheet = await updatedStyleSheet()

However, mind that awaiting blocks the execution until the function returns. This might not be the behaviour you want.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.