Node.js脚本在没有声音的情况下停止未完成

时间:2016-03-19 21:58:38

标签: javascript node.js asynchronous

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

我正在使用此great lib中的异步队列函数,但代码似乎在处理过程中没有任何消息时停止,是什么导致这种情况?

queue.drain从不调用因为执行只是消失了! 有没有办法得到脚本崩溃的原因?我尝试使用节点调试器,但没有成功。

'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);
        };
    });
}

code at pastebin

1 个答案:

答案 0 :(得分:1)

将我的评论写入答案,因为它似乎导致了解决方案:

为确保您的代码永不停滞,您必须确保始终致电System.out.print(void method);。如果任何代码路径可能没有调用它,那么异步库将停止,因为它仍在等待最后一次异步操作以表示其完成。

因此,您有几种方法可以停滞不前:

  1. 如果您的callback(err)操作实际上报告错误。
  2. 如果您的request()操作实际上返回的状态代码不是200。
  3. 如果您在请求回调处理程序中的任何位置抛出异常,例如request()JSON.parse()
  4. 这是一个更强大的实施方案:

    parseTransactions()

    仅供参考,使用现在标准的ES6承诺结构而不是带有手动回调的异步库的一个巨大优势是它使这种东西变得更简单,更加万无一失。它会自动传播错误。它会自动捕获异步异常并将其转换为错误。它使得强大的写入错误处理代码变得更加容易。