使用Node.js,我有一个任务来改善自己创建的代码。此代码执行60个HTTP请求,并为此使用库。
完成所有HTTP请求并将每个请求保存到文件需要30秒!
据说可以在3秒内通过以下方式完成这些请求:
1。正确管理异步诺言
2。缓存更聪明
3。不使用群集
4。只需添加一次费用
恐怕我不确定从哪里开始了解我能做些什么。
因此下面的代码获得了一个包含60个项目的数组,其中每个项目都是一个HTTP请求:
const exchanges = ccxt.exchanges
这些代码进入:worker = async函数,并在代码末尾:等待Promise.all(workers)等待它们完成。
我不确定从哪里开始实际可以降到3秒。如何提高此代码的速度?
'use strict';
const ccxt = require ('ccxt')
, log = require ('ololog').noLocate // npm install ololog
, fs = require ('fs')
// the numWorkers constant defines the number of concurrent workers
// those aren't really threads in terms of the async environment
// set this to the number of cores in your CPU * 2
// or play with this number to find a setting that works best for you
, numWorkers = 8
;(async () => {
// make an array of all exchanges
const exchanges = ccxt.exchanges
.filter (id => ![ 'cap1', 'cap2' ].includes (id))
// instantiate each exchange and save it to the exchanges list
.map (id => new ccxt[id] ({
'enableRateLimit': true,
}))
// the worker function for each "async thread"
const worker = async function () {
// while the array of all exchanges is not empty
while (exchanges.length > 0) {
// pop one exchange from the array
const exchange = exchanges.pop()
// check if it has the necessary method implemented
if (exchange.has['fetchTickers']) {
// try to do "the work" and handle errors if any
try {
// fetch the response for all tickers from the exchange
const tickers = await exchange.fetchTickers()
// make a filename from exchange id
const filename = '/myproject/tickers/' + exchange.id + 'Tickers.json'
// save the response to a file
fs.writeFileSync(filename, JSON.stringify({ tickers }));
} catch (e) { } //Error
}
}
}
// create numWorkers "threads" (they aren't really threads)
const workers = [ ... Array (numWorkers) ].map (_ => worker ())
// wait for all of them to execute or fail
await Promise.all (workers)
}) ()
答案 0 :(得分:1)
我认为您正在使事情变得更加复杂。您可以在map
回调中完成所有工作,然后使用Promise.all(promises)
等待所有操作完成。此过程确实比预期的“ 3秒”(在我的情况下为15秒)要长,并且会产生很多错误(例如缺少apiToken或未实现fetchTickers),但这可能是我的环境存在的问题(我以前从未使用过ccxt
,而且我没有任何apiTokens。)
这是我想出的实现,希望它可以帮助您满足您的需求:
const ccxt = require('ccxt');
const fs = require('fs');
const path = require('path');
(async () => {
const start = Date.now();
const dumps = ccxt.exchanges
.filter((id) => !['coinmarketcap', 'theocean'].includes(id))
.map(async (id) => {
const Exchange = ccxt[id];
const exchange = new Exchange({enableRateLimit: true});
if (exchange.has['fetchTickers']) {
try {
const tickers = await exchange.fetchTickers();
const dumpFile = path.join(__dirname, 'exchanges', `${id}-Tickers.json`);
await fs.promises.writeFile(dumpFile, JSON.stringify(tickers));
} catch (e) {
console.error(e);
}
}
});
await Promise.all(dumps);
const end = Date.now();
console.log(`Done in ${(end - start) / 1000} seconds`);
})();
答案 1 :(得分:0)
我尝试看看是否有可能更快地做到这一点。我尝试缓存所需的所有可能的内存。.在实际执行.fetchTickers()请求之前。
我设法从15秒降低到了9秒。但是下面的代码甚至更进一步,但是我确实收到编译错误,并且不确定我在做什么错。
错误是:
ReferenceError:未定义ID
不是将ID传递到被推送到“ exchangesArray”的“ exchange”对象中吗?
我一直在尝试将交换对象首先放入一个数组中,这需要花费所有时间:
class Challenge{
// your current code
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Challenge)) {
return false;
}
Challenge challenge = (Challenge) o;
return challenge.name.equals(name) /*&& compare other values for equality*/;
// also check for null name if it is necessary
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + name.hashCode();
//result = 31 * result + age; // other property
//result = 31 * result + passport.hashCode();// other property
return result;
}
}
然后使用此“ exchangesArray”,我尝试执行执行fetchTickers的功能:
var exchangesArray = [];