Introdução

Para executar um cenário para orquestrar e executar diversos requests em API’s diferentes (viacep.com.br, ibge.gov.br e webservicex.net) com bluebird.

package.json:

{
  "name": "lab",
  "version": "1.0.0",
  "description": "labs",
  "main": "index.js",
  "author": "André Bassi",
  "license": "ISC",
  "dependencies": {
    "async": "^2.5.0",
    "bluebird": "^3.5.0",
    "cheerio": "^1.0.0-rc.1",
    "cheerio-tableparser": "^1.0.1",
    "iconv-lite": "^0.4.18",
    "inquirer": "^3.1.1",
    "lodash": "^4.17.4",
    "request": "^2.81.0",
    "soap": "^0.19.2",
    "xml-parser": "^1.2.1"
  }
}

index.js:

'use strict';
const Promise = require('bluebird'),
    request = Promise.promisifyAll(require("request")),
    soap = require("soap"),
    parse = require('xml-parser'),
    cheerio = require('cheerio'),
    cheerioTableparser = require('cheerio-tableparser'),
    iconv = require('iconv-lite'),
    inquirer = require('inquirer'),
    dateRegex = /^(\d{5})\-?(\d{3})$/;
// Step 1: A partir do CEP de Barueri descobriremos o código do IBGE
// e o nome cidade de forma dinâmica via 
// https://viacep.com.br/ws/06440260/querty/
var step1_getIBGEDataFromCEP = function (cep) {
    var options = {
        headers: { 'user-agent': 'Mozilla/5.0' },
        url: 'https://viacep.com.br/ws/' + cep + '/querty/'
    };
    return new Promise(function (resolve, reject) {
        request.get(options, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                if (body === 'erro=true') {
                    reject('step1_getIBGEDataFromCEP - ' + error);
                } else {
                    var ibgeCode = body.split('&')[7].replace('ibge=', '');
                    resolve(ibgeCode);
                }
            }
            else {
                reject('step1_getIBGEDataFromCEP - ' + error);
            }
        });
    });
};
// Step 2: Com o código do IBGE retornaremos o número
// de habitantes e outros dados 
// via http://www.ibge.gov.br
var step2_getCityDataFromCode = function (code) {
    var options = {
        headers: { 'user-agent': 'Mozilla/5.0' },
        url: 'http://www.ibge.gov.br/home/geociencias/areaterritorial/area.php?nome=&codigo=' + code.replace('ibge=', ''),
        encoding: null
    };
    return new Promise(function (resolve, reject) {
        request.get(options, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                var cheerioOptions = {
                    normalizeWhitespace: false,
                    xmlMode: false,
                    decodeEntities: true
                };
                body = iconv.decode(body, 'ISO-8859-1');
                var $ = cheerio.load(body, cheerioOptions);
                cheerioTableparser($);
                var data = [];
                var arrayTable = $("table").parsetable(false, false, true);
                arrayTable[0].forEach(function (d, i) {
                    var row = {
                        "Codigo_UF": $("<div>" + arrayTable[0][i] + "</div>").text(),
                        "UF": $("<div>" + arrayTable[1][i] + "</div>").text(),
                        "Codigo_Municipio": $("<div>" + arrayTable[2][i] + "</div>").text(),
                        "Municipio": $("<div>" + arrayTable[3][i] + "</div>").text(),
                        "Area": $("<div>" + arrayTable[4][i] + "</div>").text()
                    };
                    data.push(row);
                })
                resolve(data.splice(1));
            }
            else {
                reject('step2_getCityDataFromCode - ' + error);
            }
        });
    });
};
// Step 3: Com o nome da cidade realizaremos uma consulta
// da previsão do tempo para o dia atual no webservice 
// http://api.openweathermap.org/
var step3_getWeatherForecast = function (address) {
    var options = {
        headers: { 'user-agent': 'Mozilla/5.0' },
        url: 'http://api.openweathermap.org/data/2.5/weather?q=' + address[0].Municipio + '&appid=dade4abc3d546cf5afee6cda56cb3995',
        json: true
    };
    return new Promise(function (resolve, reject) {
        request.get(options, function (error, response, json) {
            if (!error && response.statusCode === 200) {
                resolve(json);
            }
            else {
                reject('step3_getWeatherForecast - ' + error);
            }
        });
    });
};
// Step 4: Ainda com o código do IBGE retornaremos a área da 
// unidade territorial http://cidades.ibge.gov.br
var step4_getNumberCityDataFromCode = function (code) {
    var options = {
        headers: { 'user-agent': 'Mozilla/5.0' },
        url: 'http://cidades.ibge.gov.br/xtras/perfil.php?codmun=' + code[0].Codigo_Municipio
    };
    return new Promise(function (resolve, reject) {
        request.get(options, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                var $ = cheerio.load(body);
                cheerioTableparser($);
                var data = [];
                var arrayTable = $("table").parsetable(false, false, false);
                arrayTable[0].forEach(function (d, i) {
                    var row = {
                        "Populacao2010": $("<div>" + arrayTable[1][1] + "</div>").text(),
                        "Populacao2016": $("<div>" + arrayTable[1][0] + "</div>").text(),
                        "Gentilico": $("<div>" + arrayTable[1][5] + "</div>").text()
                    };
                    data.push(row);
                })
                resolve(data.splice(data.length - 1));
            }
            else {
                reject('step4_getNumberCityDataFromCode - ' + error);
            }
        });
    });
};
// Step 5: Através da informação fornecida da área da unidade territorial
// faremos um cálculo qualquer com de um webservice em asmx com SOAP
// que retorna xml: http://www.webservicex.net/ConvertArea.asmx?WSDL;
var step5_getUnitDataFromSOAP = function (param) {
    var options = {
        headers: { 'user-agent': 'Mozilla/5.0' },
        wsdl: 'http://www.webservicex.net/ConvertArea.asmx?WSDL'
    };
    return new Promise(function (resolve, reject) {
        soap.createClient(options.wsdl, function (err, client) {
            client.AreaUnit.AreaUnitSoap.ChangeAreaUnit({ AreaValue: param[0].Area.replace(',', ''), fromAreaUnit: 'squarekilometer', toAreaUnit: 'squarecubit' }, function (error, response) {
                if (!error) {
                    var result = parse(client.lastResponse);
                    resolve(result.root.children[0].children[0]["children"][0].content);
                }
                else {
                    reject('step5_getUnitDataFromSOAP - ' + error);
                }
            });
        });
    });
};
// Step 6: Realizamos as requests de todos os passos apartir do 
// promisses e vamos montando um retorno em JSON customizado
function execute_steps(param) {
    var cep = param; //process.argv.slice(2);
    step1_getIBGEDataFromCEP(cep).then(function (result1) {
        return Promise.all([result1,
            step2_getCityDataFromCode(result1).then(function (result2) {
                return Promise.all([result2,
                    step3_getWeatherForecast(result2).then(function (result3) {
                        return Promise.all([result3,
                            step4_getNumberCityDataFromCode(result2).then(function (result4) {
                                return Promise.all([result4,
                                    step5_getUnitDataFromSOAP(result2).then(function (result5) {
                                        return Promise.all([result5]);
                                    })
                                ]);
                            })
                        ]);
                    })
                ]);
            })
        ]);
    }).then(function (results) {
        var json = {
            "cep": cep,
            "municipio": results[1][0][0].Municipio,
            "uf": results[1][0][0].UF,
            "ibge": {
                "codigo": results[1][0][0].Codigo_Municipio,
                "censo": results[1][1][1][0][0],
            },
            "coordenada": {
                "longitude": results[1][1][0].coord.lon,
                "latitude": results[1][1][0].coord.lat
            },
            "temperatura": {
                "atual": Math.round(results[1][1][0].main.temp - 273.15),
                "minima": Math.round(results[1][1][0].main.temp_min - 273.15),
                "maxima": Math.round(results[1][1][0].main.temp_max - 273.15),
            },
            "area_km2": results[1][0][0].Area,
            "metro_cubico": results[1][1][1][1][0]
        }
        console.log(JSON.stringify(json, null, 4));
    }).catch((error) => {
        console.log(error);
    });
}
// ------------------------------------------------------------------------
// Então vamos realizar testes e validação com o CEP de Barueri por padrão
var questions = [{
    type: 'input',
    name: 'cep',
    message: 'Digite o CEP:',
    default: '04653-055',
    validate: function (value) {
        var pass = value.match(dateRegex);
        if (pass) {
            return true;
        } else {
            return 'Entre com um CEP válido';
        }
    }
}];
inquirer.prompt(questions).then(function (answers) {
    console.log('Processando...');
    execute_steps(answers.cep);
});