。然后等到承诺完成

时间:2020-07-31 00:25:30

标签: node.js asynchronous file-io promise

我有一个调用两个模块的主菜单功能。第一个获取数据并将其写入文件。第二个打开该文件并在其上运行测试。我一生无法获得第二个功能,直到第一个功能完成并创建了必要的文件。 Err始终是文件不存在。这两个文件分别按预期工作,并在命令行中单独运行。简而言之,我正在尝试:

  1. 用户输入(在带有以下代码的主菜单中)
  2. 用于创建文件的用户输入(getstock.main是一个返回1的导入模块)
  3. 打开文件并对其进行测试(test1.main是导入的模块)
const test1 = require('./daytrade2.js');
const getstock = require('./yahoodatapuller2.js');
const process = require('process'); 
var args = process.argv; 
let domefirst=function(){
  return new Promise(function(resolve,reject){
    var promisefinished=0;
    promisefinished= getstock.main(args[2])
    if(promisefinished)
    {
        resolve(1)
      }
})}

domefirst().then((result)=>{if(result)
  {test1.main(args[2],args[3])}
}).catch((err)=>{console.log(err)})
  

另外,运行以下命令会产生相同的错误

domefirst().then(()=>{test1.main(args[2],args[3])
}).catch((err)=>{console.log(err)})

进一步,这就是库存

exports.main= function(stocksym){
//var stocksym='AAPL';
const https= require('https');
var lockup=[];
fs =require('fs')
var open=[];
var close=[];
var high=[];
var low=[];
var dd=[];
var mm=[];
var yy=[];
var wkday=[];
var timestamps=[];
var volume=[];


modules = [
   'assetProfile',//0
   'summaryProfile',
   'summaryDetail',//2
   'esgScores',
   'price',//4
   'incomeStatementHistory',//6
   'incomeStatementHistoryQuarterly',
   'balanceSheetHistory',//8
   'balanceSheetHistoryQuarterly',
   'cashflowStatementHistory',
   'cashflowStatementHistoryQuarterly',
   'defaultKeyStatistics',
   'financialData',
   'calendarEvents',
   'secFilings',
   'recommendationTrend',
   'upgradeDowngradeHistory',
   'institutionOwnership',
   'fundOwnership',
   'majorDirectHolders',
   'majorHoldersBreakdown',
   'insiderTransactions',
   'insiderHolders',
   'netSharePurchaseActivity',
   'earnings',
   'earningsHistory',
   'earningsTrend',
   'industryTrend',
   'indexTrend',
   'sectorTrend' ]
    
function spacer(data){

    data=JSON.stringify(data)
    for (i=0; i<data.length;i++)
    {
        if (data[i]==',')
        
        {
            data.splice(i,0,'\n')
        }
    }
    return JSON.parse(data);
}
    

function rounder(num){

    num=Math.round((num + Number.EPSILON) * 100) / 100;
    return num;
}
var calltime=0;
var before='';
var after='';
var fileout= function(summary){
    return new Promise(function(resolve,reject){
    var promisedone= false;

    calltime+=1;
    var json= JSON.stringify(summary)
    var fname=stocksym+'.json'
    switch(calltime){
        case 1:
        before= '{"dd":';
        after= ',\n';
        break;
        case 2:
        before= '"mm":';
        after= ',\n';
        break;
        case 3:
        before= '"yy":';
        after=',\n';
        break;
        case 4:
        before= '"wkday":';
        after=',\n';
        break;
        case 5:
        before= '"open":';
        after=',\n';
        break;
        case 6:
        before= '"close":';
        after=',\n';
        break;
        case 7:
        before= '"high":';
        after=',\n';
        break;
        case 8:
        before= '"low":';
        after=',\n';
        break;
        case 9:
        before= '"volume":';
        after='}\n';
        calltime=0;
        break;
        default:
        console.log('error switch line 114');
    }
    
    
    fs.appendFile(fname,before + json+ after, function(err) { 
        if (err) throw err;
        // if no error
        console.log("Data is appended to file successfully.")
    promisedone= true;
    if(promisedone)
        {
            promisedone=false;
            resolve();
        }

    })
        
    
    })
}
    
var p1='1595203200';//startdate unix (usually 0)
var p2='1596039048';//enddate
var int='1d'; // "1d","5d","1mo","3mo","6mo","1y","2y","5y","10y","ytd","max"
var url='https://query1.finance.yahoo.com/v8/finance/chart/'+stocksym+'?symbol='+stocksym+'&period1='+p1+'&period2='+p2+'&interval='+int;
var furl=url;

https.get( furl,
    res => {
        var body= '';
        res.on('data',data=>{
            body+=(data);
            
        })
        
        res.on('end',function(){
        body=JSON.stringify(body);
        body=JSON.parse(body)
        body=JSON.parse(body)
        var d= new Date();

        for(i=0;i<body.chart.result[0].timestamp.length; i++)
        {
            timestamps.push(body.chart.result[0].timestamp[i] *1000)
            d= new Date(timestamps[i])
            
             dd.push(d.getDate());
             mm.push(d.getMonth());
             yy.push(d.getFullYear());
             wkday.push(d.getDay());
             open.push(rounder(body.chart.result[0].indicators.quote[0].open[i]));
             close.push(rounder(body.chart.result[0].indicators.quote[0].close[i]));
             high.push(rounder(body.chart.result[0].indicators.quote[0].high[i]));
             low.push(rounder(body.chart.result[0].indicators.quote[0].low[i]));
             volume.push(body.chart.result[0].indicators.quote[0].volume[i]);
            
        
        
        }
        
        fileout(dd).then(()=>{fileout(mm);
        }).then(()=>{ fileout(yy);
        }).then(()=>{ fileout(wkday);
        }).then(()=>{ fileout(open);
        }).then(()=>{ fileout(close);
        }).then(()=>{ fileout(high);
        }).then(()=>{ fileout(low);
        }).then(()=>{ fileout(volume);
        }).catch((err)=>{console.log(err)})
        

        //console.log(dd + '\n'+mm+'\n'+ yy+ '\n'+wkday+ '\n'+ open + '\n'+ close + '\n'+ high + '\n'+ low + '\n'+ volume)
        
        })
        






    })
    return 1;

}


1 个答案:

答案 0 :(得分:0)

getstock()在完成时似乎没有以任何方式回传,因此调用方无法知道何时完成。因此,您将需要对其进行修复,以便它返回完成后可以解决的承诺。您也没有办法传达回错误。

好吧,我该如何从导出的函数返回一个承诺?

它是否被导出都没有关系-它只是一个函数。您可以在fileout()中将承诺内置到getstock.main()中并返回它,方法与之相同。另外,您实际上不应该混合使用promise和普通回调。进行所有尚未返回promise的低级异步操作,并制作一个返回promise的包装,然后仅对控制流使用promise逻辑。

其他一些提示:

  1. 充分利用letconst
  2. 停止使用var
  3. 使用fs.promises界面获取已经使用诺言的fs模块功能。
  4. 使用类似got()的方式代替https.get()进行基于承诺的https提取。
  5. 摆脱您的promisedone变量。它似乎没有做任何有用的事情,并使事情看起来比实际情况更加复杂。

这里是fileout()的示例重写,它使用fs.promises.appendFile(),使用表查找而不是巨型switch(),并将所有内容切换到constlet

function fileout(summary) {
    const prefixes = [
        '{"dd":', '"mm":', '"yy":', '"wkday":', '"open":', 
        '"close":', '"high":', '"low":', '"volume":', 
    ];
    calltime += 1;
    const json = JSON.stringify(summary);
    const fname = stocksym + '.json';
    const before = prefixes[calltime - 1];
    let after = ',\n';
    if (calltime === prefixes.length) {
        after = '}\n';
        calltime = 0;
    }
    return fs.promises.appendFile(fname, before + json + after);
}

您可能还应该更改calltime变量的工作方式,因为这是副作用编程,通常不是一个好主意。也许您应该只将该变量传递到fileout()中,并让调用方对其进行递增和控制。

相同的概念可以应用于较大的功能。


这里尝试进行更大的重写以简化很多操作:

const fs = require('fs');
const got = require('got');

exports.main = async function(stocksym) {
    // create initial object that we want to write JSON version of to the file
    const stockData = {
        dd: [],
        mm: [],
        yy: [],
        wkday: [],
        open: [],
        close: [],
        high: [],
        low: [],
        volume: []
    };

    function rounder(num){
        return Math.round((num + Number.EPSILON) * 100) / 100;
    }

    // get the stock data
    const p1 = '1595203200'; //startdate unix (usually 0)
    const p2 = '1596039048'; //enddate
    const int = '1d'; // "1d","5d","1mo","3mo","6mo","1y","2y","5y","10y","ytd","max"
    const url = `https://query1.finance.yahoo.com/v8/finance/chart/${stocksym}?symbol=${stocksym}&period1=${p1}&period2=${p2}&interval=${int}`;
    console.log(url);
    const {chart} = await got(url).json();
    const timestamps = [];

    for (let i = 0; i < chart.result[0].timestamp.length; i++) {
        timestamps.push(chart.result[0].timestamp[i] * 1000);
        const d = new Date(timestamps[i])
        stockData.dd.push(d.getDate());
        stockData.mm.push(d.getMonth());
        stockData.yy.push(d.getFullYear());
        stockData.wkday.push(d.getDay());
        stockData.open.push(rounder(chart.result[0].indicators.quote[0].open[i]));
        stockData.close.push(rounder(chart.result[0].indicators.quote[0].close[i]));
        stockData.high.push(rounder(chart.result[0].indicators.quote[0].high[i]));
        stockData.low.push(rounder(chart.result[0].indicators.quote[0].low[i]));
        stockData.volume.push(chart.result[0].indicators.quote[0].volume[i]);
    }

    const fname = stocksym + '.json';
    return fs.promises.writeFile(fname, JSON.stringify(stockData));
}

这个getstock.main()的新版本返回一个承诺,该承诺在完成后会解决/拒绝。然后,调用者可以使用该承诺,通过对该承诺使用await.then().catch()来知道何时完成所有操作。