没有声音Node.js脚本停止未完成

我有一个parsing一些比特币区块链的脚本。

我从这个伟大的lib使用asynchronous队列function,但代码似乎停止没有任何消息在处理中,可能会导致这种情况?

queue.drain永远不会调用,因为执行正在消失! 有没有办法让脚本崩溃的原因? 我尝试使用节点debugging器,但没有成功。

'use strict'; var request = require ('request'); var fs = require('fs'); var async = require('async'); var blocksTotal = 0, k = 0; var data = []; var queue = async.queue((task, callback) => { request('https://blockchain.info/rawblock/' + task.hash, (err, response, body) => { if (err) console.error(err); if (response.statusCode === 200) { let parsedBlock = JSON.parse(response.body); //console.log('processing block [' + i + '/' + blocks.length + ']...'); parseTransactions(parsedBlock.tx); callback(err); }; }); }, 100); queue.drain = () => { console.log('all blocks processed. done.') } var convertTime = function(UNIX_timestamp){ let a = new Date(UNIX_timestamp * 1000); let year = a.getFullYear(); let month = +a.getMonth()+1 >= 10 ? +a.getMonth+1 : '0' + (+a.getMonth()+1); let date = a.getDate() >= 10 ? a.getDate() : '0'+a.getDate(); let hour = a.getHours() >= 10 ? a.getHours() : '0'+a.getHours(); let min = a.getMinutes() >= 10 ? a.getMinutes() : '0'+a.getMinutes(); let sec = a.getSeconds() >= 10 ? a.getSeconds() : '0'+a.getSeconds(); let time = hour + ':' + min + ':' + sec + ' ' + date + '/' + month + '/' + year ; return time; } console.log('requesting blocks...'); //make a req to blockchain to get a neat JSON request('https://blockchain.info/blocks/?format=json', (err, response, body) => { if (err) console.error(err); if (response.statusCode === 200) { let today = JSON.parse(response.body);//get today's blocks in JSON console.log('got blocks, parsing blocks...'); parseBlocks(today.blocks); }; }); //parse blocks and get transactions from it var parseBlocks = function(blocks) { console.log('got ' + blocks.length + ' blocks...') blocksTotal = blocks.length; var i = 0; blocks.forEach((block) => { queue.push({hash: block.hash}, (err) => { if(err) console.log(err); i++; //console.log('finished block ' + i + '\r'); process.stdout.write(queue.running() + ' in queue\r') }); //request('https://blockchain.info/rawblock/' + block.hash, (err, response, body) => { //if (err) console.error(err); //if (response.statusCode === 200) { //let parsedBlock = JSON.parse(response.body); //i++; //console.log('processing block [' + i + '/' + blocks.length + ']...'); //parseTransactions(parsedBlock.tx, i); //}; //}); }); }; //get UNIX timestamp and transaction value and write it to file var parseTransactions = function(transactions){ console.log('got ' + transactions.length + ' transactions from block. processing...') transactions.forEach((transaction) => { let value = 0; transaction.inputs.forEach((input) =>{ if (input.prev_out) { value += input.prev_out.value; }; }); if (value !== 0) { value = value.toString(); if (value.length > 8) { value = value.slice(-0,-8) + '.' + value.substr(-8) }else{ while(value.length !== 8){ value = '0' + value; } value = '0.' + value; }; //let info = (convertTime(transaction.time) + ';' + value + '\n'); //fs.appendFile('data', info, () => { //console.log('Data saved to file'); //}); let info = [transaction.time, value]; data.push(info); }; }); } 

代码在pastebin

把我的评论做成一个答案,因为它似乎导致了解决scheme:

为了确保你的代码永远不会停顿,你必须确保你总是调用callback(err) 。 如果任何代码path可能不会调用它,那么asynchronous库将被暂停,因为它仍在等待最后的asynchronous操作来表示完成。

因此,有几种方法会导致停滞:

  1. 如果您的request()操作实际上报告错误。
  2. 如果你的request()操作实际上返回一个不是200的状态码。
  3. 如果在请求callback处理程序(如JSON.parse()parseTransactions()任何位置引发exception。

这是一个更强大的实现:

 var queue = async.queue((task, callback) => { request('https://blockchain.info/rawblock/' + task.hash, (err, response, body) => { if (err) { console.error(err); callback(err); } else if (response.statusCode === 200) { try { let parsedBlock = JSON.parse(response.body); //console.log('processing block [' + i + '/' + blocks.length + ']...'); parseTransactions(parsedBlock.tx); callback(err); } catch(e) { callback(e); } } else { callback(new Error("statuscode was: " + response.statusCode)); } }); }, 100); 

仅供参考,使用现在标准的ES6承诺结构而不是使用手动callback的asynchronous库的巨大优势在于,它使这种工具变得更简单,更简单。 它会自动传播错误。 它会自动捕获asynchronousexception并将其转化为错误。 这使得强大的写error handling代码更容易。