javascript - Node.js 脚本未完成就停止且没有声音

标签 javascript node.js asynchronous

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

我正在使用此 great lib 中的异步队列功能但代码似乎在处理过程中停止了,没有任何消息,这可能是什么原因造成的?

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

'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

最佳答案

将我的评论变成答案,因为它似乎已经找到了解决方案:

为了确保您的代码永远不会停止,您必须确保始终调用callback(err)。如果任何代码路径可能不调用它,那么异步库将停止,因为它仍在等待最后一个异步操作来发出完成信号。

因此,您有几种方法可以使其停止:

  1. 如果您的 request() 操作实际上报告了错误。
  2. 如果您的 request() 操作实际上返回 200 以外的状态代码。
  3. 如果您在请求回调处理程序中的任何位置抛出异常,例如在 JSON.parse()parseTransactions() 中。

这是一个更强大的实现:

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 Promise 结构而不是带有手动回调的异步库的一个巨大优势是,它使这类东西变得更简单、更万无一失。它会自动传播错误。它会自动捕获异步异常并将其转化为错误。它使编写健壮的错误处理代码变得更加容易。

关于javascript - Node.js 脚本未完成就停止且没有声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36107700/

相关文章:

asynchronous - 异步 block 中的 Xamarin Android F# 更新 UI

javascript - 将现有单选按钮更改为 <a href>

javascript - JS curry 递归处理空参数

Javascript 从 ajax 响应访问嵌套对象

javascript - 用于传递产品和金额的简单 PayPal Javascript API

node.js - 通过 nodejs 查询 mongodb 显示空结果?

node.js - 在本地开发中使用时,package.json 文件是否需要每个站点的唯一名称?

javascript - promise 与 setTimeout

node.js - AWS Lambda 使用 s3 getObject 函数没有任何反应

javascript - 使带有回调/ promise 实现的 javascript 函数始终返回 promise