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

Better shoebox API #250

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Better shoebox API #250

wants to merge 2 commits into from

Conversation

ef4
Copy link
Contributor

@ef4 ef4 commented Aug 4, 2016

This adds a new higher-level API for the shoebox.

  model() {
    let fastboot = this.get('fastboot');
    return RSVP.hash({
      // In this example, we generate a random number once on the server,
      // and then the  client app will receive the same number.
      random: fastboot.withShoebox('my-random-number', () => Math.random())
    });
  }

withShoebox acts as a memoization service. On the server, the given callback will run and generate a value, which will be saved in the shoebox and then returned. On the client, the callback will not run if the value is already present in the shoebox.

withShoebox returns a promise, because the callback is allowed to return a promise.

This adds a new higher-level API for the shoebox.

```js
  model() {
    let fastboot = this.get('fastboot');
    return RSVP.hash({
      // In this example, we generate a random number once on the server,
      // and then the  client app will receive the same number.
      random: fastboot.withShoebox('my-random-number', () => Math.random())
    });
  }
```

`withShoebox` acts as a memoization service. On the server, the given callback will run and generate a value, which will be saved in the shoebox and then returned. On the client, the callback will not run if the value is already present in the shoebox.

`withShoebox` returns a promise, because the callback is allowed to return a promise.
resolve(shoebox.retrieve(key));
return;
}
Promise.resolve(fn()).then(value => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve(Promise.resolve(fn())... not then(resolve, reject)

@danmcclain
Copy link
Member

I love this API @ef4

let shoebox = this.get('fastboot._fastbootInfo.shoebox');
return shoebox && shoebox.hasOwnProperty(key);
} else {
return !!document.querySelector(`#shoebox-${key}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if shoebox is for random data (that we likely don't want displayed) should we use meta or script tags?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that could also make them addressible via import

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meta tags have limits on length that differ from browser to browser @stefanpenner

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah so big datasets

@arjansingh
Copy link
Contributor

So this immediately solves some problems I'm running into. What else (besides tests) needs to be done to get this in?

@steveszc
Copy link

It seems like the problem withShoebox is trying to solve is preventing the callback from running twice on initial pageload (once on the server, once when the client loads). However the API seems to prevent the callback from ever running on the client if the shoebox holds data matching the requested key. This seems undesirable.

I see a common use case where you only want the client to access the shoebox data one time (on initial payload) and then use the callback every subsequent time the data is requested.

Maybe it would make sense to add an argument flag or a separate API that would implement this idea of "single use" shoebox data?

@BenKingBBC
Copy link

@steveszc it's my understanding that shoebox.retrieve drops the value from the shoebox after you have retrieved it, which should mean what you're suggesting isn't an issue.

@steveszc
Copy link

@BenKingBBC That hasn't been my experience using shoebox.retrieve in my app, and I don't see anything happening in the method's source code that suggests that it removes values from the shoebox after they're retrieved.

It does look like it caches the value after it is retrieved from the DOM, but subsequent calls to shoebox.retrieve for a given key would just get the cached value instead of going back to the DOM shoebox.

I'm happy to open a separate issue if there is consensus that "single-use" use case for shoebox values should be handled by shoebox.retrieve instead of a higher-level API.

@danmcclain
Copy link
Member

@ef4 We discussed as a team, and like and approve the API, would you have bandwidth to write tests so that we can land this?

@vladucu
Copy link

vladucu commented Jun 12, 2017

this would be really awesome!

is there anything else blocking this except tests? or latest rc2 release also affects it?

resolve(shoebox.retrieve(key));
return;
}
resolve(Promise.resolve(fn()).then(value => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need wrapping Promise.resolve ? I think it will work without it too

xg-wang pushed a commit to xg-wang/ember-cli-fastboot that referenced this pull request Nov 16, 2020
Fix invalid syntax with deferRendering.
@xg-wang
Copy link
Member

xg-wang commented Apr 6, 2021

cc/ @suchitadoshi1987

@suchitadoshi1987
Copy link
Contributor

This is a good one to work on and get it in. I ll pick this one up if @ef4 is not working actively on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants