Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

JavaScript, Node.js で、標準入力した数値を変数に代入したい

解決したいこと

JavaScript, Node.jsでconsole上で入力した数値を変数に代入したいです。
Pythonのinput( )のような挙動を取ってほしいと考えています。

この記事と同様の挙動を、JavaScript, Node.js にて再現することを目的としています。

該当するソースコード

const readline = require('readline/promises');

async function input(name) {
    const readInterface = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });
    let string = await readInterface.question(name)
    readInterface.close();
    return string
}

let a = Number(input('数値1>'));
let b = Number(input('数値2>'));

console.log(a);
console.log(b);

このようなコードを記述しました

a = int(input('数字1>'))
b = int(input('数字2>'))

print(a)
print(b)

Pythonでこのように記述した場合と同様の挙動を取ってほしいと考えています。

発生している問題・エラー

image.png

async / await で今回定義した関数は、非同期処理をさせているはずですが、

let a = Number(input('数値1>'));
let b = Number(input('数値2>'));

console.log(a);
console.log(b);

この部分が一度に実行されてしまっています。
また、関数が二重に実行されており、上の画像では1を一度だけ入力したにも関わらず、2回入力されています。

補足

Promise でのコードを記述した場合、下記のように2つの変数への代入自体はできていますが、別の値を入力することはできていません。

コードの書きやすさを考えて、できればasync / awaitでの実装と、変数への代入ができればと考えています。

const readline = require('readline');
 
const inputString = prompt =>{
    const readInterface = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });
    return new Promise( resolive =>readInterface.question(prompt,
        inputString=>{
            readInterface.close();
            resolive( inputString);
        }));
};
 
const st_1 = async()=>{
    const string_1 = await inputString("文字列1 >");
 
console.log( string_1 );
}
st_1();

const st_2 = async()=>{
    const string_2 = await inputString("文字列2 >");
 
console.log( string_2 );
}
st_2();

image.png

0

4Answer

@uasi さま

無事、想定通りの挙動を示しました。
ありがとうございました。

囲まれた部分は非同期実行されるので、処理が終わるより先に ※ 以降の行が実行される可能性があります。 ※ 以降には何も書かない方がいいです。

これが結構ポイントでした。

実はコメント頂いたのち


const input_A = async () => {
    a = await input('数値1>');
}    
const input_B = async () => {
    b = await input('数値1>');
 }        
async function main() {
    await input_A();
    await input_B();
+  console.log(a);
+  console.log(b);
}

(async () => {
    await main();
  })();

-  console.log(a);
-  console.log(b);

このようなコードを書いたのですが、これではやはり console.log(a); が実行されてしまっていたのですが、async の中に記述したところ、同様の挙動を示すことがわかりました。

頂いたコードが、可読性も高く良いと思いますので、こちらのコードをベースに記事を書かせていただきます。
ありがとうございました。

1Like

input() を await すれば動くはずです。

let a = Number(await input('数値1>'));
let b = Number(await input('数値2>'));

await をつけずに async function を呼び出すと、その非同期処理を表す Promise オブジェクトが即座に返ります。よってユーザー入力を受け付ける前に2つの input() が一度に実行されてしまいます。そのとき表示される NaN は Promise を Number() で変換した結果です。

0Like

早速のご回答ありがとうございます。
勉強になりました。

ただ、まだ以下のエラーメッセージが出ているようです。

image.png

御教示いただいた内容を踏まえて、もう少し自分でも試してみます。

0Like

まだ以下のエラーメッセージが出ているようです。

では、以下のように await input() 以降の行をすべて (async () => {})() で囲んでください。

(async () => {
  let a = Number(await input('数値1>'));
  let b = Number(await input('数値2>'));

  console.log(a);
  console.log(b);
})();

// ※

囲まれた部分は非同期実行されるので、処理が終わるより先に 以降の行が実行される可能性があります。 以降には何も書かない方がいいです。


await は基本的に async 関数の中にしか書けません。最近のバージョンの Node.js では特定の条件を満たしたときトップレベル(スクリプト内で関数やクラスの外にある行)にも await が書けるため、最初の回答ではそれを期待したコードを書いたのですが、今回は条件を満たしていませんでした。この回答では無名 async 関数の中にコードを書いて即座に呼び出しています。

0Like

Your answer might help someone💌