Js promise in TW?

If we develop with ES6 js or later, we can use promise.

Has someone tried thas within js? What would be nice to have, would be the possibility to write simple code to wait until the previous I/O are done before proceeding with the next part.

Currently we can have two steps with a button, but that is not very nice (we need two separated macros).

It would certainly need an extension of the syntax for macro.

As a simpler target, has anyone coded a js macro with promise that could give a testimony and explain his coding in the TW world? And how useful it have been?

@jypre can you give a practical example where you would like. I suspect the "problem can be reframed so we do not need what you ask for.

There are many ways to get one action to trigger another, even a way to trigger actions on startup, or any other trigger such as save wiki or open tiddler. It is also possible to add conditionality into sets of actions to branch the process and even to pause the process with the action confirm.

Keep in mind macros are replicable text, tiddlywiki.com says;

A macro is a named snippet of text. WikiText can use the name as a shorthand way of transcluding the snippet. Such transclusions are known as macro calls, and each call can supply a different set of parameters that get substituted for special placeholders within the snippet.

From my perspective, tiddlywiki may provide a JS platform, even a javascript playground of sorts, but to do most things you do not need additional Javascript.

Finally, unlike a local exe TiddlyWiki need to do what we ask and return to await more user interaction right away. Tiddlywiki is not a “monitor” or batch programing platform but you could use it like that.

  1. Make absolutely sure you don’t interfere with TW’s handling of the store. In fact, I’d prefer never to touch it.

  2. Make sure you don’t interrupt events that TW would normally need for correct handling of the wiki.

  3. Go for it.

I’ve seen documentation somewhere that covers warnings like these but I don’t remember where, sorry.

EDIT: mess up ==> interfere with

@CodaCoder
For point 2, I don’t want to bypass TW normal handling, I just want to be able to say to TW: “when you’re done writing that data on this tiddler, then call that stuff”. That’s a hook, and that’s what promises are for handling nicely.

But I’m not expert enough yet to go for it. Especially, I can’t know I’m not breaking your #1. That’s why I’m asking an official way to do it from the TW gods :slight_smile:

@TW_Tones You may very well be right that it’s not a necessity. That this seems necessary could be an indication that the TW way is not obvious enough.

Pratical example I had in my mind:

  1. click on a button on a form with various $edit-text widgets
  2. as a first step, validate the input and possibbly write errors and warnings in a temp tiddler
  3. if an error, end of action (the form keeps being shown and the errors and warning are automatically shown because of TW code within the form tiddler)
  4. if things are OK but with warning’ ask for confirmation in a modal tiddler
    4.1) if no confirmation, act as for #3 with error
    4.2) if confirmation then it’s OK
  5. if it’s OK (now it should be), then write the input data into the target tiddler
  6. go the main list tiddler which should be automatically updated.

This scenario doesn’t need anything special.

But just change it a little bit: say that my data is not stored on TW tiddler but on an external database. to get it or to write it would require promise on regular js ES6. This is something I’d like to be able to do as it would allow more interoperability. But how could I do this?

https://tiddlywiki.com/#ActionConfirmWidget

I am short on time this week but hopefully some of what I share will point you in the right direction.

To confirm, fetching and saving data back to an external source on demand via an API currently isn’t possible with wikitext.

The main thing to be aware of is that in TiddlyWiki, widgets are volatile and can be destroyed and re-created as needed during the refresh process. Therefore, any long running or async tasks should not be handled by widgets that you write. Instead, the recommended approach is to send a WidgetMessage which goes up the widget tree and have a handler for your custom message in the root widget. Example code for this approach:

At this point you could let the existence of the newly created/updated tiddlers be the trigger if you only need to conditionally show or hide or update something.

If you need to trigger further actions, you want to write a change listener that checks for the changed tiddlers during each refresh cycle and when the appropriate tiddlers have been changed, triggers actions. The FileUploads plugin uses this approach, as does the core sync mechanism: tw5-file-uploads/upload-handler.js at db880c251923a0a9d9e9c2bb3d41cb7b328cd1ce · saqimtiaz/tw5-file-uploads · GitHub

A more reusable version of this approach with wikitext affordances is planned for the core but is probably yet a while away.

Alternatively, the widget message handler/listener you write could also trigger actions when the promise is resolved. Keep in mind that the context (i.e. variables that are defined) will be different when the actions are triggered compared to the context from which the widget message originated.

While it is possible to allow custom widgets to perform async tasks and trigger actions when they are completed, you risk that the widget might be destroyed before the task is complete and therefore when the promise is resolved there is no widget to handle it. I do take this approach in my WebDAV work as I prefer the syntax in the resultant wikitext and know the exact scenarios in which I intend to use it, but this very design decision is why it is not something I would publish for others to use.

Example wikitext code for fetching a file, modifying it and saving it to a different location and then triggering some actions when the tasks are successfully completed.

<$action-fetch-url $url=<<templateURL>>>
	<$action-http-put $url={{{ [<currentDir>trim:suffix[/]addsuffix[/]addsuffix{$:/temp/sq/fs/new-wiki-name}] }}} $data={{{[<sq-fetched-data>addprefix<myplugin>]}}} $successActions=<<successActions>>/>
</$action-fetch-url>
1 Like

I use promise and TS alot, take my md to tid as example, the onClick can be async: tiddlywiki-plugins/md-to-tid-button.ts at e4c5e74e79b0860e4cf5fcecc6b296ca35b69590 · tiddly-gittly/tiddlywiki-plugins · GitHub

And for my google calendar importer, the initialize code of widget can be async tiddlywiki-plugins/GoogleCalendarImportButton.ts at e4c5e74e79b0860e4cf5fcecc6b296ca35b69590 · tiddly-gittly/tiddlywiki-plugins · GitHub

2 Likes

@saqimtiaz Thank you for this panorama. Indeed this is very far away from trivial and even from simple.

So $action-fetch-url is a custom widget of yours that has been coded on purpose? The same is also surely true for $action-http-put.

Some official helpers for this kind of stuff would be most welcomed!

1 Like

Ideally any method for storing a tiddlers on or in an external database would ideally be transparent to any other process to change a tiddler.

In many ways it depends on the complexity of your input validation.

  • You can accept input into temporary fields or tiddlers and only save to the target tiddler when it has being validated, there are tricks to make this less obvious to the user.
    • Plenty of filter operators are available to validate content.
    • In the edit-text widget you can make use of the simple html validation using the type=“htmlinput type”
    • eg type=“date” type=email etc… see here many, but not all work within the edit-text widget.

@TW_Tones I am deting my stuff in temporary data tiddlers, so that I can cancel the edit and having a real commit after checking everything is OK. I would store data back to a tiddler then and after that to the database.

Of course, if I read from the database, I would directly store in the data tiddler.

My data tiddler would only be a kind of buffer for the external database.

BUT there are controls that only the database would provide like checking for uniqueness of values or integrity constraints. That would mean that after asking for commit, I may get a refusal to commit and decide what to do (keep editing most of the time).

I understand, one is a content/value validation, the other is save/commit validation of records in the database. Ideally we use different terms for clarity. Perhaps “record status” rather than validation.