Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding class to a component that uses the <await> tag throws an exception #942

Closed
NotJustClarkKent opened this issue Dec 1, 2017 · 7 comments
Assignees
Labels
reason-closed:duplicate Someone has already posted the same or a very similar issue. The original issue should be linked. status:todo type:feature A feature request

Comments

@NotJustClarkKent
Copy link

NotJustClarkKent commented Dec 1, 2017

Bug Report

Marko Version: 4.7.0

Details

Adding class to a component that uses the <await> tag throws an exception and breaks client side runtime within the development env (works with env set to production). This can be either single or multi-file within your project but using the Try Online runtime does not reproduce the problem. I also noticed the same behaviour when I had an empty component.js file for the same component. May or may not be related to #675.

Expected Behavior

A class should be able to be declared for an async component without throwing errors.

Actual Behavior

An exception is thrown once a class is added to a component.

Possible Fix

N/A - Just getting started with Marko so I don't have enough knowledge about the library to help yet.

Additional Info

Your Environment

  • Chrome 62.0.3202.94 (Official Build) (64-bit)
  • Mac OSX 10.1.6
  • Code: Using Docs example

Steps to Reproduce

  1. Create a new simple async component using the Docs snippet and run the example (success ✓)
// /components/await-example/index.marko
$ var personPromise = new Promise((resolve, reject) => {
    setTimeout(function() {
        resolve({
            name: 'Frank'
        });
    }, 1000);
});
 
<await(person from personPromise)>
    <div>Hello ${person.name}!</div>
</await>
  1. Next, add a class to the same file and run the example, with or without any methods (fails ✘)
// /components/await-example/index.marko
class { }
$ var personPromise = new Promise((resolve, reject) => {
    setTimeout(function() {
        resolve({
            name: 'Frank'
        });
    }, 1000);
});
 
<await(person from personPromise)>
    <div>Hello ${person.name}!</div>
</await>
  1. Observe the error in the browser: Uncaught Error: Not allowed

Stack Trace

Uncaught Error: Not allowed
    at AsyncVDOMBuilder.beginAsync (AsyncVDOMBuilder.js:230)
    at awaitTag (await-tag.js:146)
    at wrappedRenderer (helpers.js:106)
    at render (index.marko.js:32)
    at renderer (renderer.js:186)
    at Component.js:471
    at Object.batchUpdate [as ___batchUpdate] (update-manager.js:63)
    at Component.___rerender (Component.js:460)
    at initComponent (init-components-browser.js:103)
    at init-components-browser.js:261

  | beginAsync | @ | AsyncVDOMBuilder.js:230
  | awaitTag | @ | await-tag.js:146
  | wrappedRenderer | @ | helpers.js:106
  | render | @ | index.marko.js:32
  | renderer | @ | renderer.js:186
  | (anonymous) | @ | Component.js:471
  | batchUpdate | @ | update-manager.js:63
  | ___rerender | @ | Component.js:460
  | initComponent | @ | init-components-browser.js:103
  | (anonymous) | @ | init-components-browser.js:261
  | initServerRendered | @ | init-components-browser.js:198
  | (anonymous) | @ | (index):64
  | (anonymous) | @ | (index):64
@DylanPiercey
Copy link
Contributor

@NotJustClarkKent currently the <await> tag does not work properly in the browser which is why you are seeing this error. This is a high priority item for us that we hope to resolve as soon as possible.

@DylanPiercey
Copy link
Contributor

We will also improve the error message in this case ASAP.

@cameronbraid
Copy link
Contributor

Any idea when the <await> tag will be able to be used in the browser ?

@malipetek
Copy link

Any workarounds?

@cameronbraid
Copy link
Contributor

This is about to become a blocker for us now that we are nearing production. Is there any plan to address this in the short term ?

I'm using a workaround, which has some issues, but gets part of the way there.

ServerAwait.marko

static const onserver = typeof window == 'undefined'
<div>
	<if (onserver && input.promise)>
	  <await(p from input.promise)>
	    <include(input.renderBody)/>
	  </await>
	</if>
	<else>
		<include(input.renderBody)/>
	</else>
</div>

@cameronbraid
Copy link
Contributor

I now have a much improved marko component for working around the inability to use the <await> tag client side.

In the initial re-render on the client it preserves the server rendered html until the new promise created on the client is resolved.

NOTE : I have left off error handling for clarity.

IsomprphicAwait.marko

static const onserver = typeof(window) == 'undefined'
class {
	serverElId()  {
		return this.id + '/server'
	}

	async onCreate(input) {
		this.state = {
			serverRendered : null,
		}
		if (!onserver && input.promise) {
			let el = document.getElementById(this.serverElId())
			this.state.serverRendered = el ? el.innerHTML : null
			await input.promise
			this.state.serverRendered = null
		}
	}
}
<if (onserver && input.promise)>
    <await(p from input.promise)>
        <div id=component.serverElId()>
            <include(input.renderBody)/>
        </div>
    </await>
</if>
<else>
    <if(state.serverRendered)> 
        $!{state.serverRendered}
    </if>
    <else>
        <include(input.renderBody)/>
    </else>
</else>

Usage :

LoadAndShowData.marko

static const fetch = require("./isomorphic-fetch")
class {
  onCreate() {
    this.state = {
      data: null,
      promise : this.fetchData(),
    }
  }
  async fetchData() {
    let res = await fetch("/api/data")
    if (res.ok) {
      this.state.data = await res.json()
    }
  }
}
<div>
  <IsomprphicAwait promise=state.promise>
    Have Loaded ${JSON.STRINGIFY(data)}
  </IsomprphicAwait>
</div>

@DylanPiercey
Copy link
Contributor

Looks like this is a duplicate of #675, lets track this over there.

@DylanPiercey DylanPiercey added the reason-closed:duplicate Someone has already posted the same or a very similar issue. The original issue should be linked. label Aug 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reason-closed:duplicate Someone has already posted the same or a very similar issue. The original issue should be linked. status:todo type:feature A feature request
Projects
None yet
Development

No branches or pull requests

5 participants