Javascript readline 对象的范围

Javascript scoping of readline object

困惑为什么这段代码在第二次提示后挂起:

var readline = require('readline');

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

function curry () {
  let inputs = []
  function _curry() {
    if (inputs.length > 5) {
      for (var i = 0; i < inputs.length; i++) {
        console.log(inputs[i]);
      }
    } else {
      rl.question("Number?", function(answer) {
        inputs.push(answer)
        rl.close();
        _curry()
      });
    }
  }
  _curry()
}

curry()

===>

~/Desktop$ node curry.js

Number?1

Number?2

HANG

但是,这个:

var readline = require('readline');

function curry () {
  let inputs = []
  function _curry() {
    if (inputs.length > 5) {
      for (var i = 0; i < inputs.length; i++) {
        console.log(inputs[i]);
      }
    } else {
      var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
      });
      rl.question("Number?", function(answer) {
        inputs.push(answer)
        rl.close();
        _curry()
      });
    }
  }
  _curry()
}

curry()

工作正常:

数?1 2号 数?3 数?4 数?5 数?6 1个 2个 3个 4个 5个 6

这似乎是一个范围界定问题?阅读线没有关闭?吊装?

不,这与作用域或声明提升无关。只是您过早关闭了 readline 实例(但它似乎是异步的,因此仍然显示第二个提示)。你应该使用

function curry () {
  // better don't use a global, especially if you don't leave it open
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  let inputs = []
  function _curry() {
    if (inputs.length > 5) {
      rl.close(); // close it only once you're done with *everything*
      for (var i = 0; i < inputs.length; i++) {
        console.log(inputs[i]);
      }
    } else {
      rl.question("Number?", function(answer) {
        inputs.push(answer)
        _curry()
      });
    }
  }
  _curry()
}

我注意到我原来的 post 并不是严格的柯里化示例,而是旨在产生与此类似的功能,更具防御性柯里化,示例:

function curry(length) {
  let inputs = []
  function _curry(input) {
    inputs.push(input)
    if (inputs.length === length) {
      for (var i = 0; i < inputs.length; i++) {
        console.log(inputs[i]);
      }
    } else {
      return _curry
    }
  }
  return _curry
}

curry(4)(1)(2)(3)(4)