Creating a Command Line Interface (CLI) application in JavaScript for the browser: A guide to simulating blocking I/O

Developing a CLI application becomes quite simple with a blocking I/O API like PrintLn / ReadLn, making the process smooth and efficient.

However, the challenge arises when trying to create a terminal application that runs on a browser using JS. In this scenario, input events are asynchronous, which means you cannot block the function midway through while waiting for input without disrupting the application's state.

I am currently grappling with designing the event loop and structuring the architecture of the JavaScript code. This is especially tricky as there will be multiple levels of commands within the app, and I want to avoid falling into the trap of "callback hell". Could someone please guide me to a resource or provide tips on how to architect this design? Thank you.

Answer №1

Implementing Promises in Your Code

  1. Submit user input
  2. Disable new input submission temporarily
  3. Invoke a Promise function
  4. Show the result after the Promise has been fulfilled
  5. Enable terminal for new inputs

// Triggering the operation upon submitting
function submit(userInput) => {

  // Temporarily disable terminal
  blockTerminal();

  // Processing the user's command
  // Invoking an async Promise
  // Result displayed once operation is complete
  doSomething(userInput).then(result => {

    // Displaying outcome in the terminal
    output(result);

    // Re-enable terminal for new inputs
    releaseTerminal();
  })
}

// The asynchronous code being executed
// Returns a Promise object
function doSomething(userInput) => {
  return new Promise(resolve => {

    // Simulating a delay of 2500ms
    setTimeout(() => {
      resolve('result')
    }, 2500)
  })
}

In a live environment, replace setTimeout() with an Ajax call and use resolve(response) upon success.


Alternatively, consider exploring RxJS.

RxJS introduces Observable streams in JavaScript, which are highly effective for handling asynchronous operations. Though more complex than Promises, they offer powerful functionalities.

Answer №2

To accomplish this, you can utilize the async/await functionality.

function fetchInput(){
  return new Promise(response =>{
    document.querySelector('#submit').addEventListener('click', () => response(document.querySelector('#inputValue').value, {once:true}))
  })
}

async function execute(){
  for(let i=0;;++i){
    let input = await fetchInput()
    console.log(`${i}:${input}`)
  }
}

execute()
<input type="text" id="inputValue">
<input type="button" value="Submit" id="submit">

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Within Vuex, the object store.state.activities contains a specific key labeled "list" which initially holds an array of three items. However, when attempting to access store.state.activities.list directly, an empty array

My project is utilizing Vue. The store.state.activities object contains 2 keys, including an array named list with 3 elements. However, despite attempting to access it using store.state.activities.list, I am getting an empty array. I have experimented w ...

Steps to retrieve a rejected object with an error stored in it in the following .then() function

Within my chain of promises, there is a specific promise that needs to log an error but pass the remaining data to the next .then() const parseQuery = (movies) => { return new Promise((resolve, reject) => { const queries = Object.keys( ...

Getting the value from the object that holds the Provider/Consumer using React's Context API

Below is a demonstration using the Context API object with a library called 'react-singleton-context'. Check it out here. In my Menu.js file, I have the code snippet console.log(useSharedDataContext()). This displays an object containing Consume ...

Tips for making Ajax crawlable with jQuery

I want to create a crawlable AJAX feature using jQuery. I previously used jQuery Ajax on my website for searching, but nothing was indexed. Here is my new approach: <a href="www.example.com/page1" id="linkA">page 1</a> I display the results ...

What is the best way to simultaneously check two conditions in Vue.js?

In my current scenario, I am facing a challenge with checking both conditions simultaneously. If an attachment exists in the request but the attachment field does not exist in the form, it should display a message in the modal. Similarly, if body text exis ...

What is the proper way to define the scope for invoking the Google People API using JavaScript?

I am attempting to display a list of directory people from my Google account. export class People { private auth: Auth.OAuth2Client; private initialized: boolean = false; private accessToken: string; constructor(private readonly clientEmail: strin ...

Step-by-step guide to creating a custom wrapper in React that modifies the props for a component

Exploring React components for the first time and seeking assistance. I am interested in dynamically wrapping one component inside another and modifying its props. For instance, considering the following component: If we want to pass the key3 from a wrapp ...

Several jquery libraries are experiencing malfunctions

<head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { $(".slidingDiv").hide(); $(".show_hide").show().click ...

Exploring the beauty of ASCII art on a webpage

Having trouble displaying ASCII art on my website using a JavaScript function, the output is not as expected... This is how it should appear: And here is the code I am trying to implement for this purpose: function log( text ) { $log = $('#log&ap ...

What is the best way to show the totals on a calculator screen?

As part of my work, I created a calculator to help potential clients determine their potential savings. Everything seems to be working fine, except for the total fees not appearing for all the boxes. I believe I might be missing the correct process to add ...

What is the best method to retrieve the window object in XUL?

I'm attempting to assign an onLoad event to the current webpage through a Firefox extension. My approach involves utilizing the gBrowser object, although I am uncertain if this is the most optimal method. The goal is to establish an onLoad event for t ...

What is the reason behind being limited to sending only 5 requests if I fail to heed the data event?

I've come across some related questions while researching this topic, such as Why is node.js only processing six requests at a time?. However, I am still struggling to fully grasp the specifics. Below is a breakdown of my scenario: Firstly, let&apos ...

Utilizing JavaScript Files Instead of NPM as a Library for Open Layers: A Step-by-Step Guide

I've been attempting to get Open Layers to function in my Eclipse web development environment, but I've encountered some challenges along the way. The setup instructions provided on the Open Layers website focus mainly on using npm. Nevertheless, ...

Unable to retrieve value - angularJS

An AngularJS application has been developed to dynamically display specific values in an HTML table. The table consists of six columns, where three (Work Name, Team Name, Place Name) are fixed statically, and the remaining three columns (Service One, Servi ...

Tips for fixing the issue of "The use of getPreventDefault() is outdated. Please use defaultPrevented instead."

When attempting to fetch data for a specific user from an SQL Server database using JSON data, I encountered an error message in the console: "Use of getPreventDefault() is deprecated. Use defaultPrevented instead." Additionally, the values are not bei ...

Invoke a function in a different component following the completion of an asynchronous task in a React.js application

I am working with 2 components in my project. The first component contains a function that needs to be called after an async function in the second component completes. I am looking for a way to achieve something similar to Vue's this.$emit() function ...

Discover the best way to integrate your checkbox with your Jquery capabilities!

I am having trouble getting my 3 checkboxes to interact with the JQuery button I created. The goal is for the user to be able to select an option, and when the button is clicked, the selected options should download as a CSV file from my feeds. Below is th ...

I require the ability to access a reference parameter with a dynamically changing name within a Vue template

<div v-for="x in 4" :class="(images[x] === null) ? 'not-removable' : 'removable'" class="img-container"> <input style="display: none" type="file" ...

Is there a way to convince Python to interpret data as a multi-dimensional list instead of a string when converting from HTML?

Currently, I am working on formatting table data in HTML and then sending it to Python using the script below: var html_table_data = ""; var bRowStarted = true; var count1 = 1 $('#woTable tbody>tr').each(function () { if (count1 != 1) { ...

Is there a convenient method to combine arrays of objects in JavaScript using ellipses or an equivalent approach?

let array = [ {id: 1, data: {foo: "bar 1"}}, {id: 2, data: {foo: "bar 2"}} ]; //If ID doesn't exist, add new element to the array array = [...array, {id: 3, data: {foo: "bar 3"}}] console.log(array); //If ID exists, replace data object with new ...