Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Having a problem with promises

First full script can be found here , if you don't think the problem is where i'm posting snippets from. The problem is, I'm trying to run a promise  when the table is ready and loaded, to check for the existence of certain handouts (or maybe, eventually, tables) The error I get, as written is: ReferenceError: promise is not defined ReferenceError: promise is not defined at apiscript.js:247:21 That gets me right to my variable definition at the top of my ready: on("ready", function () { var ReadFiles = promise(function(resolve,reject){ var customTimesHandout = findObjs({_type:"handout",name:"Custom Times"}) if(customTimesHandout && customTimesHandout.length){ let CUSTOMTIMESHANDOUT = findObjs({_type:"handout",name:"Custom Times"})[0] var customTimesList = CUSTOMTIMESHANDOUT.get("notes",function(notes){ log("in the callback notes is :" + notes) var customTimesList = notes }) log("after the callback " + customTimesList) resolve(customTimesList) } else{ log("Did not find the handout") var customTimes = false reject(customTimes) } }) ReadFiles.then(function(result){ log(result) }, function(err){ log(err) }) I'm sorry for this not being the most thorough, my brain is dead at this point, and i probably won't see any responses until tomorrow morning but thanks in advance!
1561251964
GiGs
Pro
Sheet Author
API Scripter
I havent done anything with promises, so cant help you there. But I'm wondering why you'd need to use them. If the table or handouts exist, you dont need to use promises to access them. If you are creating the table'handouts in the script, you have their details in data objects in the script, and can grab what you need from it directly without going to the external objects. Please try to explain what you are trying to do, in plain English, with no code. It may be you are using the wrong approach for your task.
1561265100

Edited 1561265851
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Going to address some of GiGs' questions first: GiGs said: I havent done anything with promises, so cant help you there. But I'm wondering why you'd need to use them. If the table or handouts exist, you dont need to use promises to access them. To access the bio/info/gm notes of handouts/characters, you need to do an asynchronous callback to actually decode the content of the section, as shown in Aku's sample code. Because it's asynchronous, you can either wrap all your code in successive asynchronous callbacks (if you need to access multiple handouts); this is what I've heard referred to (appropriately) as callback hell. Using a promise allows the code to avoid the true depths of depravity of recursively nested asynchronous callbacks. Even better though is to combine a promise with the async/await capability of ES7. Now, for Aku's code question I have done several scripts using promises and/or async/await. So, your problem is two fold Aku. You define a promise a little differently than you have it; new Promise instead of just promise . Additionally, your method of resolving the promise won't work, but you haven't run into that yet because of the reference error. To resolve a promise, the resolution has to occur in the asynchronous part, not outside of it. Here's how the promise definition and resolution/rejection should go: on("ready", function () { 'use strict'; let customTimesHandout = findObjs({_type:"handout",name:"Custom Times"})[0],//this allows you to skip the need for that if(customTimesHandout &&...). findObjs always returns an array, if there were no results, then getting index 0 of the array will give null. ReadFiles = new P romise(function(resolve,reject){ if(customTimesHandout){ customTimesHandout.get("notes",function(notes){ log("in the callback notes is :" + notes); resolve(notes); }); }else{ log("Did not find the handout") var customTimes = false reject(false); } }); ReadFiles.then(function(result){ log(result) }, function(err){ log(err); }); Also, you could use async/await, to not have to enter the minor callback hell of using .then: on("ready", async function () {//denotes this as an asynchronous function that will pause during it's execution 'use strict'; let customTimesHandout = findObjs({_type:"handout",name:"Custom Times"})[0],//this allows you to skip the need for that if(customTimesHandout &&...). findObjs always returns an array, if there were no results, then getting index 0 of the array will give null. ReadFiles = await new Promise(function(resolve,reject){//the await tells the script to pause here and wait for this value to appear. Once a value is returned, the script will continue on its way if(customTimesHandout){ customTimesHandout.get("notes",function(notes){ log("in the callback notes is :" + notes); resolve(notes);//resolving the promise gives a value that unpauses the script execution }); }else{ log("Did not find the handout") var customTimes = false reject(false);//reject also gives a value to the promise to allow the script to continue } }); log(`readFiles:${readFiles}`); }); Note, that you may need to switch to something like a revealing module pattern to use the async await, but if I remember correctly the async declaration should work just fine in the on() callback function declaration. EDIT: the MDN page on promises has some good information. I'll also see if I can dig up the intros and guides to promises and async/await I read when I was diving into this stuff.
1561279100

Edited 1561288407
GiGs
Pro
Sheet Author
API Scripter
Scott C. said: Going to address some of GiGs' questions first: GiGs said: I havent done anything with promises, so cant help you there. But I'm wondering why you'd need to use them. If the table or handouts exist, you dont need to use promises to access them. To access the bio/info/gm notes of handouts/characters.  Oh yes, i completely zoned out on the handout element and was super-focussed on tables.  Your code snippets are very handy, I do need to learn how to do this myself too.
Scott,  Thanks for the code examples. I actually had tried new Promise previously, in both of the spots I mentioned above. When I do it in the on('ready'), i get an error ReferenceError: promise is not defined When I did it in the function that was doing the work, i was getting ... invalid? unrecognized? Identifier that went away when i removed "new" (this is how good of a programmer I really am, I just start stripping things out until i get a different, or no error :D) I'll whack my way through your code, but I was under the impression that doing things purely async was Bad idea(tm)
1561299761
The Aaron
Roll20 Production Team
API Scripter
It's not a bad idea, it's required for Javascript to be performant.  Javascript is single threaded, so asynchronous code is how it can avoid blocking everything while a longer operation outside the Javascript engine takes place. Anything you can write with a Promise, you should be able to write with a combination of async and await.  However, it's often tedious and difficult to get it working, so don't get too frustrated. You may also run into a case where they way async/await are supposed to behave doesn't work on the Roll20 API's Javascript engine.  It's been a while since I tried to dive into them in a script, and I have this vague recollection that there was something the engine was behind on.  
1561304547

Edited 1561305233
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Aku said: ReferenceError: promise is not defined When I did it in the function that was doing the work, i was getting ... invalid? unrecognized? Identifier that went away when i removed "new" (this is how good of a programmer I really am, I just start stripping things out until i get a different, or no error :D) I'll whack my way through your code, but I was under the impression that doing things purely async was Bad idea(tm) So my guess, based on you just removing new , as to what was happening was that you had new promise instead of new Promise and promise (all lowercase) is not anything in JS; Promise (with a capital P) is the constructor for promises. This would mean that you were trying to make a new instance of something that didn't have a prototype, and so it threw the unrecognized identifier syntaxerror because there wasn't a prototype of anything called "promise" to make a new instance of. And of course when you removed new, it became a variable reference to a variable that hadn't been defined yet, causing the referenceError from your OP. EDIT: To add to Aaron's post, async is definitely not a bad idea. In fact there are things that you literally can't do in the API without going to an async method such as very complicated calculations or iterating through many objects in large campaigns. While async processes aren't a bad idea, they can be very difficult to handle. As for the async/await implementation on the Roll20 API, I haven't run into any issues with it other than just my brain just not understanding how asynchronous functions interact. The benefit of using async/await as opposed to callback nesting or promise.then is that async/await allows you to write asynchronous code that looks like and uses the coding techniques from synchronous code.
1561382286
Ada L.
Marketplace Creator
Sheet Author
API Scripter
Promise is capitalized. Use "Promise", not "promise".
I thought I had done that both ways, but I can't honestly remember. I've got that issue resolved, now banging on another one, lol...