Node.js使用popsicle保证异步

时间:2017-06-12 01:09:20

标签: javascript node.js promise

我有一个函数,它使1个API调用返回一个Promise。 什么是转换此代码以使n次调用不同时间戳的最佳方法。我想返回一个对象,其中包含按密钥时间戳存储的未聚合数据。

此代码运行i = 1且histData未定义。

const getEthPriceHistorical= (toSymbol) => {
    var histData = {};
    var ts;
    for (let i = 1; i < 5; i++){
        ts =  new Date(new Date().getTime() - (24*i * 60 * 60 * 1000));

        if (typeof toSymbol === 'string') {
           toSymbol = toSymbol.toUpperCase();
        } else {
            toSymbol = 'USD,EUR,GBP,CHF,THB,AUD,INR';
        }
        ***** WHAT TO DO WITH THIS SINGLE PROMISE *****
        return popsicle.request({
           method: 'POST',
           url: 'https://min-api.cryptocompare.com/data/pricehistorical',

           query: {
            fsym: 'ETH',
            tsyms: toSymbol,
            timestamp: ts
           }
       })
         .use(popsicle.plugins.parse(['json']))
         .then(resp => resp.body)
         .then(data => {
            const symbols = Object.keys(data);
            histData.ts = data;
            console.log(ts, data);
        });
  }
  return histData;
}

2 个答案:

答案 0 :(得分:2)

您的代码存在以下问题:

  1. 循环中的返回,从函数返回 - 这就是循环只运行一次的原因
  2. histData异步填充该函数的本地变量。在该函数之外不可见,我在这个函数中看不到你甚至确定它是未定义的
  3. histData.ts = data会在每次迭代中更改ts属性(如果有多个) - 应为histData[ts] = data
  4. 一旦考虑到代码中的错误,希望下面的代码是自我解释的

    注意:Array.from({length: 4})在索引0 ... 3中创建一个包含四个未定义条目的数组 - 因此时间戳使用(i+1)

    的原因
    const getEthPriceHistorical= (toSymbol) => {
        if (typeof toSymbol === 'string') {
           toSymbol = toSymbol.toUpperCase();
        } else {
            toSymbol = 'USD,EUR,GBP,CHF,THB,AUD,INR';
        }
        return Promise.all(Array.from({length:4}).map((unused, i) => {
            let ts =  new Date(new Date().getTime() - (24*(i+1) * 60 * 60 * 1000));
            return popsicle.request({
               method: 'POST',
               url: 'https://min-api.cryptocompare.com/data/pricehistorical',
    
               query: {
                fsym: 'ETH',
                tsyms: toSymbol,
                timestamp: ts
               }
           })
             .use(popsicle.plugins.parse(['json']))
             .then(resp => resp.body)
             .then(data => {
                const symbols = Object.keys(data);
                return {ts, data};
            });
        })).then(results => results.reduce((result, {ts, data}) => {
            result[ts] = data;
            return result;
        }, {}));
    }
    

    或者,最后8行可以是

            .then(data => {
                const symbols = Object.keys(data);
                return {[ts]: data};
            });
        }))
        .then(results => results.reduce((result, item) => Object.assign(result, item), {}));
    }
    

    注意:无论哪种方式,什么是const symbols = Object.keys(data);除了冗余代码之外什么都不做?

答案 1 :(得分:0)

您可以将逻辑编写为同步,并通过同步执行程序nsynjs运行它:

main.js:

var nsynjs = require('nsynjs');
var popsicle = require('popsicle');

var getEthPriceHistorical = function(popsicle, toSymbol) {
    var histData = {};
    var ts;
    for (var i = 1; i < 5; i++){
        ts =  new Date(new Date().getTime() - (24*i * 60 * 60 * 1000));

        if (typeof toSymbol === 'string') {
           toSymbol = toSymbol.toUpperCase();
        } else {
            toSymbol = 'USD,EUR,GBP,CHF,THB,AUD,INR';
        }
        var data = popsicle.request({
           method: 'POST',
           url: 'https://min-api.cryptocompare.com/data/pricehistorical',

           query: {
            fsym: 'ETH',
            tsyms: toSymbol,
            timestamp: ts
           }
       })
         .data.body;

       histData[ts] = JSON.parse(data);
       console.log(ts+", got: "+data);
  }
  return histData;
}

var ctx = nsynjs.run(getEthPriceHistorical,{},popsicle,null,function(histData){
    console.log('done: '+ JSON.stringify(histData));
});

请在此处运行此代码:https://runkit.com/amaksr/node-popsicle