Storing and retrieving data - Message Mixer project

Hi there!
Doing the Message Mixer project I encountered some issues with the logic of super-encoder.js, in particular with storing and retrieving data to/from a global variable.
I searched the web to try to find a solution on my own and I came up with two possible different causes:

  1. Issue may be caused by asynchronicity of the code
  2. Something about process.exit() that somehow makes the variable “local” to the current session (?).

However I haven’t figured out the exact reason yet. Here’s my code for super-encoder.js:

// Import the encryptors functions here.
const {caesarCipher, symbolCipher, reverseCipher} = require('./encryptors.js');

//initialize empty array to store encoding parameters
let randomParams = [];

//encode randomly choosing one of three methods
function encodeMessage(str){
  const i = Math.floor(Math.random()*3);
  const randomAmount = Math.floor(Math.random()*26);
  //store random generated encoding parameters for future use
  randomParams.push(i, randomAmount);
  process.stdout.write("i: "+i+"\tAmount: "+randomAmount+"\n");
  if(i===0){
    process.stdout.write("**Encryption method: CaesarCipher**\n  Encoding...\n  "+caesarCipher(str, randomAmount)+"\n");
  }else if(i===1){
    process.stdout.write("**Encryption method: symbolCipher**\n  Encoding...\n  "+symbolCipher(str)+"\n");
  }else{
    process.stdout.write("**Encryption method: reverseCipher**\n  Encoding...\n  "+reverseCipher(str)+"\n");
  }
};

//decode remembering which of the three methods was used
function decodeMessage(str, randomParams){
  const i = randomParams[0];
  const randomAmount = randomParams[1];
  process.stdout.write("i: "+i+"\tAmount: "+randomAmount+"\n");
  if(i===0){
    process.stdout.write("**Encryption method: CaesarCipher**\n  Decoding...\n  "+caesarCipher(str, -randomAmount)+"\n");
  }else if(i===1){
    process.stdout.write("**Encryption method: symbolCipher**\nDecoding...\n  "+symbolCipher(str)+"\n");
  }else{
    process.stdout.write("**Encryption method: reverseCipher**\nDecoding...\n  "+reverseCipher(str)+"\n");
  }
};

// User input / output.
const handleInput = (userInput) => {
  const str = userInput.toString().trim();
  if(process.argv[2] === 'encode'){
    encodeMessage(str);
  }else if(process.argv[2] === 'decode'){
    decodeMessage(str, randomParams);
  }else{
    process.stdout.write('Did not recognize the command. Use "encode" to encrypt a message or "decode" to decrypt one.\n> ');
    process.exit()
  };
  process.exit()
};

// Run the program.
if(process.argv[2] === 'encode'){
  process.stdout.write('Enter the message you would like to encrypt...\n> ')
}else if(process.argv[2] === 'decode'){
  process.stdout.write('Enter the message you would like to decrypt...\n> ')
};
process.stdin.on('data', handleInput);

Step 10 asks: Now, in super-encoder.js , define decodeMessage() to provide a function that reverses the encoding of encodeMessage().
I expected that the function decodeMessage() would have been able to retrieve the data stored in the array randomParams after encodeMessage() has been executed.
This way I would satisfy step10 by simply storing in i the encoding method used and in randomAmount the encoding parameter required by the caesarCipher() method. However this is not the case:

Can anyone help me understand why i and randomAmount are undefined?

There is a noticeable absence of return statements, and an abundance of print statements. Neither returns anything but undefined.

I thought and tried to return the encoding variables i and randomAmount from encodeMessage() to then store them into randomParams in handleInput(). However the result is always undefined for both of them.

function encodeMessage(str){
  const i = Math.floor(Math.random()*3);
  const randomAmount = Math.floor(Math.random()*26);
  //store random generated encoding parameters for future use
  process.stdout.write("i: "+i+"\tAmount: "+randomAmount+"\n");
  if(i===0){
    process.stdout.write("**Encryption method: CaesarCipher**\n  Encoding...\n  "+caesarCipher(str, randomAmount)+"\n");
  }else if(i===1){
    process.stdout.write("**Encryption method: symbolCipher**\n  Encoding...\n  "+symbolCipher(str)+"\n");
  }else{
    process.stdout.write("**Encryption method: reverseCipher**\n  Encoding...\n  "+reverseCipher(str)+"\n");
  };
  return [i, randomAmount]
};
const handleInput = (userInput) => {
  const str = userInput.toString().trim();
  if(process.argv[2] === 'encode'){
    randomParams = encodeMessage(str);
  }else if(process.argv[2] === 'decode'){
    decodeMessage(str, randomParams);
  }else{
    process.stdout.write('Did not recognize the command. Use "encode" to encrypt a message or "decode" to decrypt one.\n> ');
    process.exit()
  };
  process.exit()
};

The randomParams parameter is still undefined, meanwhile calling decodeMessage(str, encodeMessage(str)); it accesses the encoding variables alright, but it also encodes first (being a callback) which is not really what I wanted to achieve.
image_2021-04-06_073315

Which method do you think should I return but I’m not doing?

I also thought about rewriting the handleInput() completely making it asking the user to insert the encoding variables used to encode a string, that would be neat but it is outside the scope of the exercise.

Unless we out and out analyze your code, there is no straight answer. The objective of each function should be to return an encoded or decoded message that can be passed on down the line. Is your code doing that?

Are you making it easy for the user?

Aside

What if all our functions did only one thing? What if they never sent anything, ever, to stdout, only return? Think on that.

I thought the exercise wanted us only to display the encoded and/or decoded message to the console, so I gave the functions only that purpose: “do some elaboration and display messages”, to answer your rhetorical(?) question, the code is not passing down the line that information.
The only info I wanted to pass down was the randomParams array but I can’t retrieve it later on, I don’t understand why, hence this thread, but if you think it is a problem of lack of returning statements then I will investigate on that. Cheers!

I think so, I redacted cleanly the messages to the console, the user interacts only through that, so yes I think so. But I understand that if you ask that, you don’t think so, why’s that?

How the user would interact with the program then? I feel confused now :confused:

I assume the cause of the misunderstanding is the role of the terminal: You installed the node environment (or codecademy did it for you, if your using their environment rather than a local editor like VSCode), because you want to be able to test your work without taking a detour to the browser’s console.

The user (in the exercise it would be the developers at Super Encoder LLC) is supposed to be able to use the encodeMessage and decodeMessage functions in their code for whatever purpose they want without writing them themselves.

Usually the process would be that the company who wrote the message encoder program (In the exercise that would be Message Mixer Inc., you working there)
deploys a package and uploads it at https://npmjs.com/
The developers at Super Encoder LLC download it and install it on their computers.
In their JS file they’d then import it with something like const messageencoder = require('encoder').
And then they’d use it like:

const displayMessage = (yourMessage) => {
 return `Your message encoded looks like: ${messageencoder.encodeMessage(yourMessage)`;
}

If you print the message to the console, your depriving the user of the possibility to use the functions for their own purposes.

Hello mirja_t,
I think I didn’t make myself clear and I truly apologise for that.

I deviated from the 9th step of the exercise on purpose because I wanted to do something a little different, step 9 stated:

Use the three encryption methods to complete the encodeMessage() function by passing the input str parameter into one encryption function and then passing the returned value to the next encryption function. encodeMessage() should return the final encoded message.

The hint associated was definitive clear on that:

const encodeMessage = (str) => {
  return reverseCipher(symbolCipher(caesarCipher(str, 6)));
}

However all this doesn’t really concern my initial question, which was (and still is):

Why if I store some variable during the execution of the code I cannot retrieve it after process.exit() has been called?

I figured it must happen for the aforementioned two reasons:

  1. Issue may be caused by asynchronicity of the code
  2. Something about process.exit() that somehow makes the variable “local” to the current session (?).

However I remembered that in Ruby on Rails there is this thing of creating a sandbox in the terminal to test on stuff and then killing it off would delete everything. I figured it may be something similar in Node, the variable being associated to the current session, once the session terminates everything is sandboxed away (?).

I am also thinking about: what should come next?
I mean returning anything from encodeMessage() and decodeMessage() should go somewhere outside the current session, or they get lost too once process.exit() is executed I guess.

I very much appreciate all the effort and time spent into answering me.

Cheers to you and @mtf!

1 Like

Hi @usernamegiapreso
ah, ok. Reading the thread, I thought it was just about successfully finishing the program following the instructions.

I don’t know for sure, but I don’t think so: You do not force the exit, so the REPL can finish the program. The stored value of the global variable is available during the loop run with ‘encrypt’.
For each function you run a separate loop, and I assume that the data is dismissed after each loop.

My initial interpretation was that just the encodeMessage and decodeMessage functions themselves should be made available to the user, that’s why you should be returning from them. But reading it again; I’m not sure anymore. Anyway, both functions are supposed to receive separate inputs, which means that the decrypt function doesn’t expect data from the encrypt function.

1 Like