Why an empty (and not undefined) storage result?

Trying out storage. This function is called on an initial render of a page through the trigger listener below:

const getGlobalDLDict = () => {
  console.log( `getGlobalDLDict`);
  const dlDict = storage.get( 'DLAppValues');
  if (dlDict === undefined) {
    const context = useProductContext();
    const space = useState(async () => await fetchSpace(context.spaceKey));
    console.log(`All info about my space: ${JSON.stringify(space, null, 2)}`);
  }
  else {
    console.log(`All info about my storage: ${JSON.stringify(dlDict, null, 2)}`);
  }
  return dlDict;
};

export async function dl_handleTriggerTest( event, context) {
  console.log( `dl_handleTriggerTest`);
  const myDict = await getGlobalDLDict();
  console.log(`All info about my context: ${JSON.stringify(context, null, 2)}`);
  console.log(`All info about my event: ${JSON.stringify(event, null, 2)}`);
;}

This is shown in forge logs:

INFO    2023-03-16T16:04:36.705Z 29b0ec58-196c-4be5-ab1d-b1bdb745d547 dl_handleTriggerTest
INFO    2023-03-16T16:04:36.706Z 29b0ec58-196c-4be5-ab1d-b1bdb745d547 getGlobalDLDict
INFO    2023-03-16T16:04:36.725Z 29b0ec58-196c-4be5-ab1d-b1bdb745d547 All info about my storage: {}
INFO    2023-03-16T16:04:36.851Z 29b0ec58-196c-4be5-ab1d-b1bdb745d547 All info about my context: {
  "installContext": "ari:cloud:confluence::site/fa4a1400-8b16-4e54-9cae-55b61b7a8598"
}
INFO    2023-03-16T16:04:36.852Z 29b0ec58-196c-4be5-ab1d-b1bdb745d547 All info about my event: {
  "atlassianId": "70121:eeb17000-6682-4e4a-a2b6-73bdedb2ef10",
  "suppressNotifications": false,
  "content": {

etc.

I have never stored anythoing in app storage.

According to https://developer.atlassian.com/platform/forge/runtime-reference/storage-api/:

Gets a value by key. If the key doesn’t exist, the API returns undefined.

So, if I know the key doesn’t exist I should get undefined, right? But that is not what I get. Why?

That’s perhaps poor wording on our part.

The return type of storage.get is Promise<...> and when the key is not found we get Promise<undefined>.

Another interesting problem with JS is JSON.stringify(new Promise(() => {})) === '{}' which is why this error isn’t obvious.

I see. Not being a seasoned JS developer, how do I test if a key exists or not in app storage in this Promise situation?

A question probably more appropriate for stack overflow or the like but I can help out quickly here

const getGlobalDLDict = async () => {
  console.log( `getGlobalDLDict`);
  const dlDict = await storage.get( 'DLAppValues');
  if (dlDict === undefined) {
    const context = useProductContext();
    const space = useState(async () => await fetchSpace(context.spaceKey));
    console.log(`All info about my space: ${JSON.stringify(space, null, 2)}`);
  }
  else {
    console.log(`All info about my storage: ${JSON.stringify(dlDict, null, 2)}`);
  }
  return dlDict;
};

export async function dl_handleTriggerTest( event, context) {
  console.log( `dl_handleTriggerTest`);
  const myDict = await getGlobalDLDict();
  console.log(`All info about my context: ${JSON.stringify(context, null, 2)}`);
  console.log(`All info about my event: ${JSON.stringify(event, null, 2)}`);
}

I haven’t tested this but I believe this is correct.

The key difference is the additional await and async.

1 Like

I also see you’re using useState in a strange way.

You may face problems with this.

The useState hook is taken from React. If you’re unfamiliar this might help

1 Like

Definitely strange way, indeed. I was largely unfamiliar with React itself (this is what you get when you use documentation, internet search, and trial-and-error-with-console.log as way to find out how stuff works). I have been studying React and now understand a bit more.