【发布时间】:2020-07-22 14:07:56
【问题描述】:
我正在更改问题,因为我认为我的解释有误。
我目前正在使用 1 个 API 端点来接收我需要的数据。我需要添加第二个端点以同时接收来自两个端点的数据,将它们合并在一起并存储在数据库中。
第一个端点 -
https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=30m&limit=1
第二个端点 - https://api.binance.com/api/v3/ticker/24hr?symbol=${symbol}
这是我从第一个端点接收数据的方式
const getBTCData = async symbol => {
let data = await fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=30m&limit=1`).then(res => res.json());
const btcusdtdata = data.map(d => {
return {
Open: parseFloat(d[1]),
High: parseFloat(d[2]),
Low: parseFloat(d[3]),
Close: parseFloat(d[4]),
Timespan: 30,
}
});
console.log(btcusdtdata);
saveToDatebase(symbol, btcusdtdata);
};
我从这个端点返回 4 个参数
我需要从第二个端点获取一个参数并将其与第一个端点的参数结合起来。
我需要来自第二个端点的这个参数 - "quoteVolume": "15.30000000"
我发现Promise.all 可以成为一个解决方案,但我不明白如何从 2 个 api 返回数据并将它们合并到一个对象中以保存在 MongoDB 中。
完整代码
小解释 - 目标是从两个端点获取数据并将其存储在 MongoDB 中,并计算过去 200 天 quoteVolume 的平均值。
const { MongoClient } = require('mongodb');
const schedule = require('node-schedule');
const fetch = require("node-fetch");
require('dotenv').config()
"use strict"; // This is ES6 specific. Help's to run code faster(IMPORTANT FOR NOTIFICATION SYSTEM)
const nodemailer = require("nodemailer");
const symbols = ["ADABTC", "AEBTC","AIONBTC"];
//a descriptive name helps your future self and others understand code easier
const getBTCData = async symbol => {
let data = await fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=30m&limit=1`).then(res => res.json());
const btcusdtdata = data.map(d => {
return {
Open: parseFloat(d[1]),
High: parseFloat(d[2]),
Low: parseFloat(d[3]),
Close: parseFloat(d[4]),
Volume: parseFloat(d[5]),
Timespan: 30,
}
});
console.log(btcusdtdata);
saveToDatebase(symbol, btcusdtdata);
//recursive functions are complicated, we can get rid of it here
//by moving the responsibility to the caller
};
//helper function for an awaitable timeout
const sleep = ms => new Promise(res => setTimeout(res, ms));
const j = schedule.scheduleJob('* * * * * *', async() => {
//expand this function to be responsible for looping the data
for (let symbol of symbols) {
await getBTCData(symbol);
await sleep(8000);
}
});
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return date + ' ' + time;
};
const saveToDatebase = async(symbol, BTCdata) => {
try {
const url = 'mongodb://username:password@ip.adress.com:port/dbname?retryWrites=true&w=majority';
let dateTime = getDateTime();
let db = await MongoClient.connect(url, { useUnifiedTopology: true });
const dbo = db.db('Crypto');
const myobj = Object.assign({ Name: symbol, Date: dateTime }, BTCdata[0]);
await dbo.collection(symbol).insertOne(myobj);
const average = await dbo.collection(symbol).aggregate([{
$addFields: {
DateObj: {
$regexFindAll: { input: "$Date", regex: "\\d+" }
}
}
},
{
$set: {
DateObj: {
$dateFromParts: {
year: { $toInt: { $arrayElemAt: ["$DateObj.match", 0] } },
month: { $toInt: { $arrayElemAt: ["$DateObj.match", 1] } },
day: { $toInt: { $arrayElemAt: ["$DateObj.match", 2] } },
hour: { $toInt: { $arrayElemAt: ["$DateObj.match", 3] } },
minute: { $toInt: { $arrayElemAt: ["$DateObj.match", 4] } },
second: { $toInt: { $arrayElemAt: ["$DateObj.match", 5] } },
timezone: "Europe/London"
}
}
}
},
{
$match: {
$expr: {
$gte: ["$DateObj", { $subtract: ["$$NOW", 201 * 60 * 60 * 24 * 1000] }]
}
}
},
{
"$group": {
_id: null,
"Volume": {
"$avg": "$Volume"
}
}
}
]).toArray();
console.log('1 document inserted');
console.log(BTCdata[0].Volume);
console.log(average[0].Volume);
const RealTimeDataVolume = parseInt(BTCdata[0].Volume);
const HistoricalTimeDataVolume = parseInt(average[0].Volume); // 201 DAYS VOLUME HERE 3286033.4285714286
const DayTimesRealAverage = RealTimeDataVolume * 48; // 1 DAY REAL TIME DATA HERE 196579344
const Previous200dVolume = (HistoricalTimeDataVolume - DayTimesRealAverage) / 200;
const MultiplePrevious200dVolume = Previous200dVolume * 5;
if (MultiplePrevious200dVolume < DayTimesRealAverage) {
async function main() {
let transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true, // true for 465, false for other ports
auth: {
user: process.env.DB_USER, // OUR ALARM EMAIL
pass: process.env.DB_PASS, // OUR ALARM PASSWORD
},
});
let info = await transporter.sendMail({
from: process.env.DB_USER, // sender address
to: process.env.DB_RECEIVER, // list of receivers
subject: symbol + 'Is UP', // Subject line
text: symbol + " IS UP", // plain text body
});
console.log("Message sent: %s", info.messageId, symbol);
}
main().catch(console.error);
} else {
console.log('false');
}
console.log(DayTimesRealAverage);
console.log(MultiplePrevious200dVolume);
} catch (e) {
console.error(e)
}
};
【问题讨论】:
-
您可以像调用第一个 API 一样调用第二个 API,只需更改 URL 并从响应中提取
quoteVolume。 -
您可以像现在一样拨打电话。此外,您可能希望使用 request-promise 或 Axios 来轻松处理内容。如果你这样做有什么问题吗?
-
@Yos 这是同时调用两个 API 的方式吗?我需要来自一个 api 的一些数据和来自另一个 api 的一些数据
-
只需复制粘贴调用 klines api 的代码并更改第二个 api 的 url。我不明白这似乎是个问题
-
@Yos 我更新了主要问题,很抱歉,但我仍然对如何从第二个 API 和第一个 API 接收数据感到困惑。
标签: javascript node.js