Has anyone found a way to fully use Promise() on C...
# suitescript
b
Has anyone found a way to fully use Promise() on Client Triggers that expect an immediate Boolean response (e.g. saveRecord, validateField) When returning the Promise() to saveRecord(), saveRecord obviously coerces the Promise to a truthy/non-null value, so allows saveRecord to complete, even if the Promise resolves false. We find it ever so annoying to write Promise() code for fieldChange, PageInit, etc., but synchronous code for validateField, saveRecord, etc. I built a workaround that returns false to save record, queues a Promise, and then upon resolve of TRUE, re-invokes the Save button - however this approach uses jQuery and doesn't work with Save & Copy, Save & New, etc... Example of scenario:
b
your approach is probably as close as you are going to get with suitescript
πŸ‘ 1
dont know why your workaround doesnt work with save and new and the likes
p
I just think it doesn’t make sense to use promises in clientscripts. No point using ugly hacks just for the sake of it? (Just my uneducated opinion)
b
@battk I thought it might be.. from what I have tested, the saveRecord event doesn't include a parameter for save/save&copy etc, so when we re-invoke the "Save" button in the .then call, we just invoke the normal "Save" button, so any other action is lost. @PNJ The blocking nature of Synchronous XMLHttp requests in JavaScript is nasty (and I imagine why SuiteScript 2.0 introduced Promises to the API) , we have observed some customer accounts where several bundles are installed and these all deploy client scripts to a single record (e.g. 6 x saveRecord entry points onto Employee record) these all run one-by-one blocking on-hover events and other setTimeouts/setIntervals within the browser. We have even seen in some cases the "Kill Webpage" pop-up where some accounts have so many synchronous scripts. This is where we see the value async promises add to the user experience πŸ™‚ With all the above said, we do find adding all this boilerplate code (ugly hacks, as you said) a bit untidy, so we tend to revert to non-promise to ensure code maintainability. The benefits of async Promises however are not to be ignored
b
if you are already willing to use jQuery, you can add your own event listeners to the other buttons to tell which was clicked and then click them again
a
Hey folks, good discussion! Can you provide an example/code snipet of how you would expect the promise API in SuiteScript to work?
πŸ‘ 1
I'd like to bring this to the product team, but I need some help to make the case clear
b
i would say @Benjamin Carson's screenshot is fairly clear. he wants to return a Promise that resolves to a boolean instead of returning boolean in saveRecord.
πŸ‘ 1
j
One pretty vanilla use case is to use the N/ui/dialog.confirm function in a saveRecord trigger. It's a nicer user experience than window.confirm, but it returns a boolean promise instead of a boolean. The only way to use it in saveRecord is to "re-click" the save button using javascript, which is hacky and brittle.
πŸ‘ 1
m
You beat me to it @jkabot, and we've resorted to just sticking with window.confirm() to avoid those hacks. Same thing in validateField functions (and with other N/ui/dialog methods).
An alternate solution to that would be a non-promise version of those methods if possible.
πŸ‘ 1
b
With SuiteScript 2.1 using ES6, I have wondered about async await for this sort of thing.. However I would think the NS function calling the saveRecord would still need to be tweaked to support. Syntax becomes much cleaner as well
m
@Benjamin Carson async/await is just eye candy for promises
πŸ‘ 1
@MTNathan
An alternate solution to that would be a non-promise version of those methods if possible
I'm pretty sure that's not possible in JavaScript.
b
window.confirm is what we revert to as well for save events, which is a real shame , as the dialog.create() method in particular is really useful, most Customers dislike the window.confirm as it is "OK" or "Cancel" (in chrome) which sometimes reads a bit odd if its a Yes/No answer. @michoel @MTNathan Yes sadly the Dialog members always yield a promise, only way around it I have ever got working is as below
m
@michoel I figured as much. It's just a shame to see such an otherwise-useful module become essentially unusable in certain situations.
b
@Albert Margarit (NS Eng Lead) Hi Albert, the Screenshots and examples should hopefully make the intended use case clear πŸ™‚ One very good example to take to the product team which has been mentioned here a few times would certainly be the N/dialog: create/confirm/alert members and how these cannot be use natively in entry points such as saveRecord as the Boolean response is needed right away. There are two ways this could work : 1. nlapiSaveRecord handles a Promise response - this has got to be the cleanest approach 2. The saveRecord entry point is handed in an "event" parameter within "context" (this event may store the save, save & copy, save & new etc.) if this "event" had a .allow() or .block() method, it would allow use of methods like the n/Dialog confirm, .Promise.then() would run once the user makes their choice, and this "event" could then be allowed or blocked depending on user choice - which could instruct saveRecord to allow or block. The general feeling we get is that we have all of these lovely .promise methods and modules like n/Dialog, which can only be used in some scenarios (pageInit, fieldChange, etc), so for consistency we tend to fallback to the native browser methods / synchronous methods , which is a shame I am just throwing some ideas out there, but the below is how point 2 might look: