Skip to main content
Solved

How to create text without need of doing it in async function


Branislav_Toman

Hi, I am trying to create text const with const rowText = figma.createText() and then specifying font with rowText.fontName = {family: "Open Sans", style: "Regular"}.

I am getting this Error:

I tried fixing it according to error instructions, but I am not using it in a async function. Is there a way to bypass it somehow?

Whole code:


figma.showUI(__html__, {height: 250, title: "Table Generator"})

// Calls to "parent.postMessage" from within the HTML page will trigger this
// callback. The callback will be passed the "pluginMessage" property of the
// posted message.

figma.ui.onmessage = msg => {

  // One way of distinguishing between different types of messages sent from
  // your HTML page is to use an object with a "type" property like this.

  if (msg.type === 'actionGenerate') {
    
    const {countRows, countColumns} = msg.formDataObj

    // Generate main (parent) frame with custom name and properties for proper auto-layouting
    const parentFrame = figma.createFrame()
    parentFrame.name = 'Table ' + countRows + 'x' + countColumns
    parentFrame.layoutMode = "HORIZONTAL"
    parentFrame.paddingTop = 25
    parentFrame.paddingRight = 16
    parentFrame.paddingBottom = 25
    parentFrame.paddingLeft = 16
    parentFrame.primaryAxisSizingMode = "AUTO"
    parentFrame.counterAxisSizingMode = "AUTO"
    
    // Generate lines according to 'countRow', name and resize them
    for (let i = 0; i < countColumns; i++) {

      const column = figma.createFrame()
          column.name = 'Column ' + (i+1)
          column.layoutMode = "VERTICAL"
          column.primaryAxisSizingMode = "AUTO"
          column.counterAxisSizingMode = "AUTO"
      
      parentFrame.appendChild(column)

      for (let j = 0; j < countRows; j++) {

        const row = figma.createFrame()
          row.name = 'Row ' + (j+1)
          row.layoutMode = "VERTICAL"
          row.primaryAxisSizingMode = "AUTO"
          row.counterAxisSizingMode = "AUTO"

        column.appendChild(row)

          // Generate lines
          const rowLine = figma.createLine()
            rowLine.name = 'Line ' + (j+1)
            rowLine.resize((908/countColumns),0)
      
            // Change color of lines
            const colorR = 224 / 255,
                  colorG = 224 / 255,
                  colorB = 224 / 255

            rowLine.strokes = [{type: "SOLID", color: {r: colorR, g: colorG, b: colorB}}]        

            row.appendChild(rowLine)
          
          const rowText = figma.createText()
            let description = "Edit me"
            figma.loadFontAsync({ family: "Open Sans", style: "Regular" })
            rowText.fontName = {family: "Open Sans", style: "Regular"}
            rowText.name = 'Item ' + (j+1)
            rowText.characters = description

            row.appendChild(rowText)

        // Select generated table and zoomm-in
        const selectFrame : FrameNode[] = []
        selectFrame.push(parentFrame)
        figma.currentPage.selection = selectFrame
        figma.viewport.scrollAndZoomIntoView(selectFrame)
      }
    }

    figma.closePlugin('Table generated successfully :)')
  } else if (msg.type === 'actionExit') {
    
    figma.closePlugin();
  }

};

Best answer by Gleb

If this message is shown right after running the plugin, it means the promise (async function) didn’t finish yet and you already closed the plugin. This happens because your decision to use a promise instead of an async function desynchronized the threads. If you used an async function, you could just await for the fonts to load and continue doing the plugin things and close it like normal. But since you are now not waiting for the fonts to load, your plugin probably closes before the promise returns. Fonts don’t load and the text doesn’t get set so you get empty text boxes. Make sure you understand async functions well: Async functions - making promises friendly. Promises are just a different type of async functions so you won’t be able to magically run away from using async functions by using a promise.

View original

17 replies

Branislav_Toman

I am not sure how do you mean that or how to use it in this case, could you elaborate, please?


Branislav_Toman

What argument resolve() requires?


tank666
  • 4871 replies
  • September 13, 2022

In this example, a value for resolve() is not required.


Branislav_Toman

It wants an argument, but I have no idea what kind of
image


tank666
  • 4871 replies
  • September 14, 2022

Is your code not compiling due to this syntax highlighting? Or are you just worried that something is highlighted? Try passing any value: undefined, boolean, string, etc.

But I repeat again:


Gleb
  • Power Member
  • 4708 replies
  • September 14, 2022

It should say that when you hover


Branislav_Toman

It is not compiling and error message looks like this:

After I give it any kind of value it compiles, but does not work properly when ran as plugin in Figma.


Branislav_Toman

This is console output in Figma after running the plugin:


tank666
  • 4871 replies
  • September 16, 2022

Thank you.

Quoting from the documentation:

However, note that loadFontAsync returns a Promise. Even a Promise resolves immediately, it still needs to round-trip to the JavaScript event loop.
loadFontAsync | Plugin API

Thus, you can try the following code:

let font = {family: "Open Sans", style: "Regular"};
figma.loadFontAsync(font).then(() => {
	let rowText = figma.createText();
	rowText.fontName = font;
	rowText.characters = "Edit me";
});

Branislav_Toman

Text is still not showing up, only empty text nodes. Console output looks like this even after 10min of waiting:

There are still font loads in progress. Please ensure closePlugin is not called until after the font loading has resolved.


Gleb
  • Power Member
  • 4708 replies
  • September 16, 2022

Do you close the plugin and see this message only after 10 minutes of waiting or is it displayed immediately after your plugin runs?


Gleb
  • Power Member
  • 4708 replies
  • Answer
  • September 16, 2022

If this message is shown right after running the plugin, it means the promise (async function) didn’t finish yet and you already closed the plugin. This happens because your decision to use a promise instead of an async function desynchronized the threads. If you used an async function, you could just await for the fonts to load and continue doing the plugin things and close it like normal. But since you are now not waiting for the fonts to load, your plugin probably closes before the promise returns. Fonts don’t load and the text doesn’t get set so you get empty text boxes. Make sure you understand async functions well: Async functions - making promises friendly. Promises are just a different type of async functions so you won’t be able to magically run away from using async functions by using a promise.


Branislav_Toman

It is displayed right away. I commented out figma.closePlugin() and text loaded, thanks for that 🙂 But what can I do for plugin to close automatically right after font is loaded?


tank666
  • 4871 replies
  • September 16, 2022

You should only call figma.closePlugin() after the asynchronous code has completed. Therefore, you need to put this in asynchronous code and add a condition for the plugin to close.


Gleb
  • Power Member
  • 4708 replies
  • September 17, 2022

You need to synchronize the code. I find it pretty simple and intuitive to do it by using an async function. But if you don’t want to use one, you can synchronize promises as well, but it’s less intuitive and requires more code.


Branislav_Toman

I tried it with async function, but did not work for me, that is why I went the other way. Should’ve spent more time trying to deal with async 😕


Gleb
  • Power Member
  • 4708 replies
  • September 20, 2022

Here is what roughly your code should look like on a global level:

async function main() {
  // some regular code
  let a = 5
  // some async code
  await loadFont()
  // close plugin at the end
}

main()

Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings