节点正在等待已经终止的超时
node is waiting for a timeout that already killed
我设置了发回错误的超时时间。问题是,如果我需要用 clearTimeOut() 清除超时,它确实会杀死它,我可以看到,因为 errTimeout 的 _kill 的值在调试器中显示为 true。但出于某种原因,节点仍然保留 运行 脚本,直到 timeOutPeriod 结束。我想它不会真正在生产中产生问题,因为调用函数将接收返回值。但它一直在等待而不是终止脚本,这仍然让我很生气。
return new Promise((resolve,reject) => {
function checkResponse () {
//creates a timeout that returns an error if data not receieved after the specified time.
let errTimeout = setTimeout(reject, config.timeOutPeriod);
//the +1 is there because we originally reduced one, we need to use the physical number now.
if(layerKeycodes.length !== (rows+1) * (columns+1)){
//if the array is not complete, check again in 100 ms
setTimeout(checkResponse, 100);
} else {
//clear the error timeout
clearTimeout(errTimeout);
//send the layerKeycodes to the calling function
resolve(layerKeycodes);
}
}
看起来这段代码是您试图从这个 other question 中装入 getLayerKeycodes()
的代码,以便以某种方式知道何时从您的键盘硬件接收到所有数据。
我将说明如何在不使用计时器的情况下插入它。这是您在另一个问题中的开头:
你原来的函数
const getLayerKeycodes = (keyboard, layer, rows, columns) => {
//array that stores all the keycodes according to their order
let layerKeycodes = [];
//rows and columns start the count at 0 in low level, so we need to decrease one from the actual number.
columns --;
rows --;
//loop that asks about all the keycodes in a layer
const dataReceived = (err, data) => {
if(err) {
return err;
}
// push the current keycode to the array
// The keycode is always returned as the fifth object.
layerKeycodes.push(data[5]);
console.log(layerKeycodes);
};
for (let r = 0 , c = 0;c <= columns; r ++){
//callback to fire once data is receieved back from the keyboard.
if(r > rows){
c++;
//r will turn to 0 once the continue fires and the loop executes again
r = -1;
continue;
}
//Start listening and call dataReceived when data is received
keyboard[0].read(dataReceived);
//Ask keyboard for information about keycode
// [always 0 (first byte is ignored),always 0x04 (get_keycode),layer requested,row being checked,column being checked]
keyboard[0].write([0x01,0x04,layer,r,c]);
}
console.log(layerKeycodes);
}
手动创建承诺在完成所有 rows/columns
后解决
并且,您可以将完成检测代码合并到 dataReceived()
函数中,无需任何计时器,也无需像这样重新处理其余大部分逻辑:
const getLayerKeycodes = (keyboard, layer, rows, columns) => {
return new Promise((resolve, reject) => {
//array that stores all the keycodes according to their order
const layerKeycodes = [];
const totalCells = rows * columns;
let abort = false;
//rows and columns start the count at 0 in low level, so we need to decrease one from the actual number.
columns--;
rows--;
// function that gets with keyboard data
function dataReceived(err, data) => {
if (err) {
abort = true; // set flag to stop sending more requests
reject(err);
return;
}
// push the current keycode to the array
// The keycode is always returned as the fifth object.
layerKeycodes.push(data[5]);
// now see if we're done with all of them
if (layerKeycodes.length >= totalCells) {
resolve(layerKeycodes);
}
}
// loop that asks about all the keycodes in a layer
for (let r = 0, c = 0; c <= columns; r++) {
// stop sending more requests if we've already gotten an error
if (abort) {
break;
}
//callback to fire once data is receieved back from the keyboard.
if (r > rows) {
c++;
//r will turn to 0 once the continue fires and the loop executes again
r = -1;
continue;
}
//Start listening and call dataReceived when data is received
keyboard[0].read(dataReceived);
//Ask keyboard for information about keycode
// [always 0 (first byte is ignored),always 0x04 (get_keycode),layer requested,row being checked,column being checked]
keyboard[0].write([0x01, 0x04, layer, r, c]);
}
}
}
}
承诺读取功能的简化版
而且,这里有一个更简单的版本,它提供了读取功能,因此我们可以在其上使用 await
,然后只需使用一个 async
函数和一个双重嵌套的 for
循环更简单的循环机制。
const util = require('util');
async function getLayerKeycodes(keyboard, layer, rows, columns) => {
// promisify the keyboard.read()
const readKeyboard = util.promisify(keyboard[0].read).bind(keyboard[0]);
//array that stores all the keycodes according to their order
const layerKeycodes = [];
// loop that asks about all the keycodes in a layer
for (let rowCntr = 0; rowCntr < rows; rowCntr++) {
for (let colCntr = 0; colCntr < columns; colCntr++) {
// Start listening and collect the promise
const readPromise = readKeyboard();
// Ask keyboard for information about keycode
// [always 0 (first byte is ignored),always 0x04 (get_keycode),layer requested,row being checked,column being checked]
keyboard[0].write([0x01, 0x04, layer, rowCntr, colCntr]);
// wait for data to come in
const data = await readPromise;
// push the current keycode to the array
// The keycode is always returned as the fifth object.
layerKeycodes.push(data[5]);
}
}
return layerCodes;
}
这也确保我们发送一个写入,然后等待该写入的数据返回,然后再发送下一个写入,这似乎是一种处理硬件的潜在更安全的方式。您的原始代码会立即触发所有可能有效的写入操作,但读取操作似乎可以按任何顺序返回。这保证了 layerCodes 数组中的顺序顺序,这看起来更安全(我不确定这是否与此数据有关)。
最后一个版本中的错误处理在某种程度上是由 async
函数和承诺自动处理的。如果读取 returns 一个错误,那么 readPromise
将自动拒绝,这将中止我们的循环并反过来拒绝异步函数返回的承诺。因此,我们不必 abort
检查具有手动创建的 promise 的先前函数是否具有。
现在,当然,我没有能力 运行 测试其中的任何一个,所以可能在某处有一些错别字,但希望你能完成其中的任何一个并看到这些工作原理的概念。
我设置了发回错误的超时时间。问题是,如果我需要用 clearTimeOut() 清除超时,它确实会杀死它,我可以看到,因为 errTimeout 的 _kill 的值在调试器中显示为 true。但出于某种原因,节点仍然保留 运行 脚本,直到 timeOutPeriod 结束。我想它不会真正在生产中产生问题,因为调用函数将接收返回值。但它一直在等待而不是终止脚本,这仍然让我很生气。
return new Promise((resolve,reject) => {
function checkResponse () {
//creates a timeout that returns an error if data not receieved after the specified time.
let errTimeout = setTimeout(reject, config.timeOutPeriod);
//the +1 is there because we originally reduced one, we need to use the physical number now.
if(layerKeycodes.length !== (rows+1) * (columns+1)){
//if the array is not complete, check again in 100 ms
setTimeout(checkResponse, 100);
} else {
//clear the error timeout
clearTimeout(errTimeout);
//send the layerKeycodes to the calling function
resolve(layerKeycodes);
}
}
看起来这段代码是您试图从这个 other question 中装入 getLayerKeycodes()
的代码,以便以某种方式知道何时从您的键盘硬件接收到所有数据。
我将说明如何在不使用计时器的情况下插入它。这是您在另一个问题中的开头:
你原来的函数
const getLayerKeycodes = (keyboard, layer, rows, columns) => {
//array that stores all the keycodes according to their order
let layerKeycodes = [];
//rows and columns start the count at 0 in low level, so we need to decrease one from the actual number.
columns --;
rows --;
//loop that asks about all the keycodes in a layer
const dataReceived = (err, data) => {
if(err) {
return err;
}
// push the current keycode to the array
// The keycode is always returned as the fifth object.
layerKeycodes.push(data[5]);
console.log(layerKeycodes);
};
for (let r = 0 , c = 0;c <= columns; r ++){
//callback to fire once data is receieved back from the keyboard.
if(r > rows){
c++;
//r will turn to 0 once the continue fires and the loop executes again
r = -1;
continue;
}
//Start listening and call dataReceived when data is received
keyboard[0].read(dataReceived);
//Ask keyboard for information about keycode
// [always 0 (first byte is ignored),always 0x04 (get_keycode),layer requested,row being checked,column being checked]
keyboard[0].write([0x01,0x04,layer,r,c]);
}
console.log(layerKeycodes);
}
手动创建承诺在完成所有 rows/columns
后解决并且,您可以将完成检测代码合并到 dataReceived()
函数中,无需任何计时器,也无需像这样重新处理其余大部分逻辑:
const getLayerKeycodes = (keyboard, layer, rows, columns) => {
return new Promise((resolve, reject) => {
//array that stores all the keycodes according to their order
const layerKeycodes = [];
const totalCells = rows * columns;
let abort = false;
//rows and columns start the count at 0 in low level, so we need to decrease one from the actual number.
columns--;
rows--;
// function that gets with keyboard data
function dataReceived(err, data) => {
if (err) {
abort = true; // set flag to stop sending more requests
reject(err);
return;
}
// push the current keycode to the array
// The keycode is always returned as the fifth object.
layerKeycodes.push(data[5]);
// now see if we're done with all of them
if (layerKeycodes.length >= totalCells) {
resolve(layerKeycodes);
}
}
// loop that asks about all the keycodes in a layer
for (let r = 0, c = 0; c <= columns; r++) {
// stop sending more requests if we've already gotten an error
if (abort) {
break;
}
//callback to fire once data is receieved back from the keyboard.
if (r > rows) {
c++;
//r will turn to 0 once the continue fires and the loop executes again
r = -1;
continue;
}
//Start listening and call dataReceived when data is received
keyboard[0].read(dataReceived);
//Ask keyboard for information about keycode
// [always 0 (first byte is ignored),always 0x04 (get_keycode),layer requested,row being checked,column being checked]
keyboard[0].write([0x01, 0x04, layer, r, c]);
}
}
}
}
承诺读取功能的简化版
而且,这里有一个更简单的版本,它提供了读取功能,因此我们可以在其上使用 await
,然后只需使用一个 async
函数和一个双重嵌套的 for
循环更简单的循环机制。
const util = require('util');
async function getLayerKeycodes(keyboard, layer, rows, columns) => {
// promisify the keyboard.read()
const readKeyboard = util.promisify(keyboard[0].read).bind(keyboard[0]);
//array that stores all the keycodes according to their order
const layerKeycodes = [];
// loop that asks about all the keycodes in a layer
for (let rowCntr = 0; rowCntr < rows; rowCntr++) {
for (let colCntr = 0; colCntr < columns; colCntr++) {
// Start listening and collect the promise
const readPromise = readKeyboard();
// Ask keyboard for information about keycode
// [always 0 (first byte is ignored),always 0x04 (get_keycode),layer requested,row being checked,column being checked]
keyboard[0].write([0x01, 0x04, layer, rowCntr, colCntr]);
// wait for data to come in
const data = await readPromise;
// push the current keycode to the array
// The keycode is always returned as the fifth object.
layerKeycodes.push(data[5]);
}
}
return layerCodes;
}
这也确保我们发送一个写入,然后等待该写入的数据返回,然后再发送下一个写入,这似乎是一种处理硬件的潜在更安全的方式。您的原始代码会立即触发所有可能有效的写入操作,但读取操作似乎可以按任何顺序返回。这保证了 layerCodes 数组中的顺序顺序,这看起来更安全(我不确定这是否与此数据有关)。
最后一个版本中的错误处理在某种程度上是由 async
函数和承诺自动处理的。如果读取 returns 一个错误,那么 readPromise
将自动拒绝,这将中止我们的循环并反过来拒绝异步函数返回的承诺。因此,我们不必 abort
检查具有手动创建的 promise 的先前函数是否具有。
现在,当然,我没有能力 运行 测试其中的任何一个,所以可能在某处有一些错别字,但希望你能完成其中的任何一个并看到这些工作原理的概念。