การรับค่าจากคีย์บอร์ด บน Node.js

18 March 2021

การรับค่า (Inputs) คือการรับข้อมูลจากภายนอกเข้ามาในโปรแกรม การรับค่าสามารถเกิดขึ้นได้หลายช่องทาง เช่น การรับค่าจากคีย์บอร์ด การอ่านค่าจากไฟล์ หรือการส่งข้อมูลผ่านทางเน็ตเวิร์ค และ Node.js สนับสนุนรูปแบบการรับค่าทั้งหมด สำหรับในบทนี้ เราจะพูดถึงการรับค่าจากคีย์บอร์ด ซึ่งเป็นวิธีรับค่าพื้นฐานของการเขียนโปรแกรมแบบ Command line นี่เป็นเนื้อหาในบทนี้

  • การรับค่าจากคีย์บอร์ดด้วยโมดูล readline
  • การรับค่าเป็นตัวเลข
  • ตัวอย่างโปรแกรมคำนวณเกรด

การรับค่าจากคีย์บอร์ดด้วยโมดูล readline

การรับค่าเป็นเรื่องพื้นฐานในการเขียนโปรแกรม โปรแกรมส่วนมากมักจะมีการรับค่าจากผู้ใช้งานเพื่อนำเข้ามาทำงานในโปรแกรม ยกตัวอย่างเช่น เมื่อคุณเขียนโปรแกรมบวกตัวเลข ผู้ใช้งานโปรแกรมควรจะกรอกค่าที่ต้องการหาผลรวมเข้ามายังโปรแกรมได้ ซึ่งวิธีการรับค่าที่ง่ายที่สุดคือผ่านทางคีย์บอร์ด และนี่เป็นสิ่งที่เราจะพูดถึงในบทนี้

Node.js มีโมดูลมาตรฐานที่ให้เราสามารถใช้สำหรับรับค่าจากคียบอร์ดได้นั่นคือโมดูล readline สำหรับตัวอย่างแรกในบทนี้ มาเขียนเป็นโปรแกรมที่ถามให้ผู้ใช้กรอกชื่อ จากนั้นแสดงคำกล่าวทักทายชื่อดังกล่าวออกทางหน้าจอ

greeting.js
const readline = require('readline');

const readInterface = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

readInterface.question('What\'s your name? ', name => {
    console.log(`Hi ${name}!`);
    readInterface.close();
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

What's your name? Metin
Hi Metin!

เมื่อรันโปรแกรม โปรแกรมจะถามให้กรอกชื่อและเรากรอกชื่อเป็น "Metin" และมันแสดงชื่อที่รับเข้ามานี้ออกทางหน้าจอ ต่อไปเรามาดูกันว่าแต่ละส่วนของโปรแกรมนั้นมีการทำงานอย่างไรบ้าง

const readline = require('readline');

เพื่อใช้งานเมธอดสำหรับการรับค่า เราได้ทำการนำเข้าโมดูล readline ด้วยฟังก์ชัน require นี่เป็นโมดูลมาตรฐานบน Node.js ที่ใช้สำหรับการรับค่าผ่านทางคีย์บอร์ดแบบทีละบรรทัด

const readInterface = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

จากนั้นเป็นการสร้างอินเตอร์เฟซสำหรับการรับค่าและการแสดงผลด้วยเมธอด createInterface โดยเชื่อมเข้ากับ process.stdin และ process.stdout ทั้งสองเป็นออบเจ็คของ Stream ที่ให้ช่วยให้เราสามารถรับค่าและแสดงผลผ่านทาง Command line ได้โดยตรง

readInterface.question('What\'s your name? ', name => {
    console.log(`Hi ${name}!`);
    readInterface.close();
});

เพื่อรับค่าเราใช้เมธอด question โดยระบุพารามิเตอร์แรกเป็นข้อความที่จะแสดงเป็นคำถามก่อนการรับค่า และพารามิเตอร์ที่สองเป็นฟังก์ชัน Callback ที่จะถูกเรียกใช้งานเมื่อการรับค่าเสร็จสิ้น

ในการทำงานของเมธอดจะรอให้ผู้ใช้กรอกข้อมูลผ่านทางคีย์บอร์ดจนกว่าจะกดปุ่ม Enter เมื่อไหร่ก็ตามที่ปุ่ม Enter ถูกกดนั้นหมายความว่าการรับค่าเสร็จสิ้น และฟังก์ชัน Callback จะถูกเรียกใช้งานพร้อมกับค่าที่รับส่งเข้ามาได้ผ่านทางพารามิเตอร์ name

readInterface.close();

หลังจากการรับค่าเสร็จสิ้น เราจำเป็นต้องปิด Stream สำหรับการรับค่าด้วยเมธอด close เพื่อคืน Cursor ของโปรแกรมบน Command line ให้สามารถทำอย่างอื่นได้ต่อไป

การทำงานของเมธอด question เป็นแบบ Asynchronous นั่นหมายความว่ามันไม่บล็อคการทำงานโปรแกรมในระหว่างรอการรับค่า เมื่อไหร่ก็ตามที่การรับค่าเสร็จสิ้น ฟังก์ชัน Callback จะถูกเรียกใช้งานพร้อมกับค่าที่รับมาได้ส่งเข้าไปในฟังก์ชัน

นั่นหมายความว่าเมื่อคุณต้องการทำงานบางอย่างหลังจากรับค่าเสร็จสิ้น คุณจะต้องทำมันในฟังก์ชัน Callback ที่เราส่งเป็นพารามิเตอร์ที่สองของเมธอด question ลองจินตนาการว่าถ้าคุณต้องการรับค่าอีกค่าหนึ่งหลังจากที่รับค่าแรกเสร็จไปแล้ว มาดูตัวอย่างต่อไป

ในตัวอย่างนี้ เราจะเขียนโปรแกรมสำหรับรับค่าสองค่า ตอนแรกจะเป็นการรับค่าชื่อก่อนและจากนั้นรับเอาค่าภาษาเขียนโปรแกรม สังเกตว่าการรับค่าจะเป็นแบบลำดับซึ่งสามารถเขียนโปรแกรมได้ดังต่อไปนี้

favorite_language.js
const readline = require('readline');

const readInterface = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

readInterface.question('What\'s your name? ', name => {
    console.log(`Hi ${name}!`);

    readInterface.question('What\'s you favorite language? ', lang => {
        console.log(`Nice! ${lang} is my favorite too!`);
        readInterface.close();
    });
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

What's your name? Metin
Hi Metin!
What's you favorite language? JavaScript
Nice! JavaScript is my favorite too!

ในตัวอย่าง โปรแกรมทำการรับค่าสองครั้ง ครั้งแรกสำหรับรับชื่อของผู้ใช้งานโปรแกรม จากนั้นรับเอาภาษาเขียนโปรแกรมโปรดของเขาด้วย ในการรับค่าครั้งที่สอง เราจะต้องทำมันในฟังก์ชัน Callback ของการรับค่าครั้งแรก

readInterface.question('What\'s you favorite language? ', lang => {
    console.log(`Nice! ${lang} is my favorite too!`);
    readInterface.close();
});

เนื่องจากเมธอดทำงานในรูปแบบ Asynchronous ที่ใช้ฟังก์ชัน Callback กำหนดการทำงานเมื่อการรับเสร็จสิ้น ดังนั้นทุกอย่างที่เราต้องการทำหลังจากการรับค่าจะต้องทำมันภายในฟังก์ชัน Callback เหมือนกับที่คุณเห็น ในกรณีนี้คือการรับค่าภาษาเขียนโปรแกรมนั่นเอง

ในภาษา JavaScript เวอร์ชัน ECMAScript 2015 (ES6) คุณสามารถใช้คำสั่ง Async/Await ร่วมกับ Promise เพื่อทำให้การรับค่าทำงานในรูปแบบ Synchronous ได้ นี่จะมีประโยชน์เมื่อเราต้องการให้โปรแกรมรับค่าเป็นแบบลำดับและช่วยลดการใช้ฟังก์ชัน Callback ที่ซ้อนกันได้

การรับค่าเป็นตัวเลข

ในการรับค่าผ่านทาง Command line ค่าที่ได้รับเข้ามาโดยเมธอด question จะเป็น String เสมอ ดังนั้นหากคุณต้องการรับค่าในรูปแบบตัวเลข คุณสามารถทำได้โดยการแปลง String เป็นตัวเลขด้วยฟังก์ชันในภาษา JavaScript

ในตัวอย่างนี้ เป็นโปรแกรมที่รับค่าตัวเลขจำนวนเต็มผ่านทางคีย์บอร์ด จากนั้นโปรแกรมจะบอกว่าค่าที่รับเข้ามาเป็นเลขคู่หรือเลขคี่ นี่เป็นโค้ดของโปรแกรม

odd_or_even.js
const readline = require('readline');

const readInterface = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

readInterface.question('Enter a number: ', number => {
    // Convert string to integer
    number = parseInt(number);

    if (number % 2 == 1) {
        console.log(`${number} is odd number.`);
    } else {
        console.log(`${number} is even number.`);
    }

    readInterface.close();    
});

นี่เป็นผลลัพธ์ในการทำงานของโปรแกรม เมื่อเรากรอก 1 และ 4 เป็นค่านำเข้าของโปรแกรมตามลำดับ

Enter a number: 1
1 is odd number.
Enter a number: 4
4 is even number.

เช่นเดียวกับตัวอย่างก่อนหน้า เราได้นำเข้าโมดูล readline จากนั้นใช้เมธอด question สำหรับการรับค่าโดยส่งพารามิเตอร์แรกเป็นคำถามก่อนการรับค่า และพารามิเตอร์ที่สองเป็นฟังก์ชัน Callback ที่จะทำงานเมื่อการรับค่าเสร็จสิ้น

readInterface.question('Enter a number: ', number => {
    // Convert string to integer
    number = parseInt(number);
    ...

เมื่อผู้ใช้กดปุ่ม Enter เราจะได้รับค่าที่กรอกเข้ามาผ่านทางตัวแปร number และอย่างที่เราบอกค่าที่ได้รับนั้นจะเป็น String เสมอ ดังนั้นเราใช้ฟังก์ชัน parseInt สำหรับแปลงค่าที่รับเข้ามาให้เป็นตัวเลขจำนวนเต็มเพื่อนำมาใช้งาน

คุณสามารถใช้ฟังก์ชันอื่นๆ ในภาษา JavaScript สำหรับแปลง String เป็นตัวเลขได้ เช่น คลาส Number หรือฟังก์ชัน parseFloat เป็นต้น

อย่างไรก็ตาม ในกรณีที่ค่าที่รับมาเป็นค่าของตัวเลขที่ไม่ถูกต้อง ผลลัพธ์การแปลงอาจไม่เป็นไปตามที่คาดหวัง ยกตัวอย่างเช่น ถ้าหากผู้ใช้โปรแกรมกรอกค่าที่ไม่เป็นตัวเลข คุณจะได้รับค่า NaN จากการแปลง ดังนั้นควรตรวจสอบข้อมูลที่รับเข้ามาก่อนนำไปใช้เสมอ

ตัวอย่างโปรแกรมคำนวณเกรด

สำหรับตัวอย่างสุดท้ายในบทนี้ เราจะมาเขียนโปรแกรมสำหรับคำนวณเกรดโดยให้ผู้ใช้กรอกคะแนนที่ทำได้ และโปรแกรมจะบอกว่าคุณได้เกรดอะไร

Mateo เป็นคุณครูของโรงเรียนแห่งหนึ่ง เขาต้องการเขียนโปรแกรมเพื่อช่วยให้นักเรียนสามารถดูเกรดของตัวเองได้ เพียงแค่กรอกคะแนนที่ทำได้ลงไปในโปรแกรม นี่เป็นโปรแกรมคำนวณเกรดของ Mateo ที่เขาสามารถส่งให้นักเรียนใช้เพื่อคำนวณดูเกรด

grade.js
const readline = require('readline');

const readInterface = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

readInterface.question('Enter your score 0 - 100: ', (score) => {
    readInterface.close();

    score = Number(score);

    if (score < 0 || score > 100) {
        console.log('You entered an invalid score.');
        return;    
    }

    if (score >= 80) {
        console.log('Excellent! You got A.');
    } else if (score >= 70) {
        console.log('Good job! You got A.');
    } else if (score >= 60) {
        console.log('Not bad! C is your grade.');
    } else if (score >= 50) {
        console.log('Becareful! D is your grade.');
    } else {
        console.log('Try it harder, You have F.');
    }
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรมเมื่อเรากรอกค่าต่างๆ ของคะแนน

Enter your score 0 - 100: 85
Excellent! You got A.
Enter your score 0 - 100: 62
Not bad! C is your grade.
Enter your score 0 - 100: 120
You entered an invalid score.

ในตัวอย่างนี้ สิ่งใหม่ที่เราได้ทำเพิ่มเข้ามาคือการใช้ฟังก์ชัน Number สำหรับแปลงคะแนนเป็นตัวเลข การใช้ฟังก์ชันนี้มันจะยังคงรักษาตัวเลขที่เป็นทศนิยม หรือคุณสามารถใช้ฟังก์ชัน parseFloat ก็ได้เช่นกัน นอกจากนี้ เรายังตรวจสอบว่าคะแนนต้องอยู่ระหว่าง 0 - 100 ซึ่งเป็นช่วงของคะแนนที่อนุญาติ

จากนั้นเป็นการคำนวณหาเกรดจากคะแนนที่รับเข้ามา โดยตรวจสอบกับเงื่อนไขที่เราได้กำหนดไว้ เช่น คะแนนมากว่า 80 จะได้เกรด A และน้อยกว่า 50 จะได้เกรด F เป็นต้น และนี่เป็นเพียงตัวอย่างง่ายๆ สำหรับการรับค่าเพื่อนำมาใช้งานในโปรแกรมเท่านั้น คุณสามารถเขียนโปรแกรมอะไรก็ได้ที่ต้องการและใช้ประโยชน์จากการรับค่า เพื่อทำให้โปรแกรมสามารถตอบสนองกับผู้ใช้งานได้

ในบทนี้ คุณได้เรียนรู้เกี่ยวกับการทำให้โปรแกรมสามารถติดต่อกับผู้ใช้งานได้ผ่านการรับค่าจากทางคีย์บอร์ดเพื่อนำมาใช้งานในโปรแกรม โดยการใช้ฟังก์ชันจากโมดูลมาตฐานของ Node.js เราได้แสดงตัวอย่างการรับค่าในรูปแบบของ String และตัวเลข และโปรแกรมคำนวณเกรดที่มีการรับค่า

บทความนี้เป็นประโยชน์หรือไม่?Yes·No