简体   繁体   中英

How to return the value from an async function

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.

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

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM