Wait for an event to occur within a function in Javascript for Skulpt

孤者浪人 提交于 2019-11-30 09:24:59

问题


I want to change the Sk.inputfun() for Skulpt to let the user type in a <textarea> and hit the ENTER key to submit. I need to pass in a single function to Skulpt that gets user input, however, I can't find any way to do this other than prompt().

The only way I could think to do this was to delay the return using setTimeout() until an event triggered the enter key button and changed a flag.

var enterPressed = false;
$("#output").keyup(function(e){
    if((e.keyCode || e.which) == 13) { //Enter keycode
      enterPressed = true;
    }
});

and then to wait for the change I had:

 Sk.configure({
    inputfun: function (prompt) {
       function checkFlag() {
          if(enterPressed) {
             enterPressed = false
             return $('#output').val();
          } else {
             window.setTimeout(checkFlag, 100);
          }
       }
       return checkFlag();
    },
    inputfunTakesPrompt: true,
    output: outf,
    read: builtinRead
 });

However this dosen't work for a few reasons. a) The timeout function can't return a value, and b) Timeout dosen't even delay the return function, and it simply returns nothing.

I have tried using .done() as well, but couldn't get it to work.

There doesn't seem to be any way to do this that I could find online, any help would be much appreciated!


回答1:


You need to return a Promise from your inputfun, which you then resolve when return gets pressed. (If you're not familiar with Promises, they are well worth a look - <grossSimplification>they let you write asynchronous code using synchronous logic</grossSimplification>).

Something like this (using your code as a base):

Sk.configure({
   inputfun: function () {
      // the function returns a promise to give a result back later...
      return new Promise(function(resolve,reject){
         $("#input").on("keyup",function(e){
             if (e.keyCode == 13)
             {
                 // remove keyup handler from #output
                 $("#input").off("keyup");
                 // resolve the promise with the value of the input field
                 resolve($("#input").val());
             }
         })
      })
   },
   output: outf,
   read: builtinRead
});

I've assumed an input element with an ID of input is receiving stdin. Looking at your OP, you were talking about a textarea (although JQuery .val() should work fine on this). On the basis of what you've called your textarea ("output") it seems that your intention was for both stdin and stdout to involve a shared textarea. If so, I'm not sure how you're going to be able to distinguish between what's been generated by stdin and what's been (subsequently) entered by the user. Thus the code above assumes a separate input field.

I had a similar use case to you, and the way I gave the illusion of an integrated console for both stdin and stdout was to have a span with contenteditable at the end of my output div. On keycode == 13, before I resolved the promise and sent back what the user had typed, I took the text out of the input span and appended it to the output div.



来源:https://stackoverflow.com/questions/43733896/wait-for-an-event-to-occur-within-a-function-in-javascript-for-skulpt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!