How to handle Promise.all properly: Getting undefined - javascript

I'm trying to get an array filled with the info back from some requests made to different REST APIs.
I thought about using Promise.all to do that but for some reason, it yields an Array with a bunch of undefined inside.
[ undefined, undefined, undefined, undefined ]
Here's my code:
var _ = require("lodash");//Used exclusively to check if the result from the request is an object
var ccxt = require("ccxt");//External library used to make the requests
let pairs = ["ETH/EUR", "BTC/EUR", "LTC/EUR", "BCH/EUR"]; //Array on which the Promise.all is based
function test(p) {
for (var i = 0; i < ccxt.exchanges.length; i++) { //Looping through all the rest APIs
let exchange = new ccxt[ccxt.exchanges[i]](); //Defining each API to make the requests
if (exchange.hasFetchOrderBook) {
exchange //Beginning of the request
.fetchOrderBook(p)
.then(order => {
if (_.isObject(order) && order.bids[0][1]) {
let now = Math.floor(new Date());
order.mkt = exchange.name;
order.pair = p;
order.ping = now - order.timestamp;
return order; //Return the result of the request
}
})
.catch(e => {});
}
}
}
Promise.all(pairs.map(test)) //Making the requests based on the Pairs Array
.then(res => {
console.log(res); //Logging the results ==> [undefined, undefined, undefined, undefined] for some reason...
})
.catch(e => {
console.log(e);
});
I know that the requests are correctly being made since if I console.log the order within the loop, I get the correct results -- Example of the result when logging:
{ bids:
[ [ 12009.52, 0.0468 ],
[ 12008.5, 0.0227 ],
[ 12007.48, 30.9321 ],
[ 12006.46, 0.0537 ],
[ 12005.45, 0.0157 ],
[ 12004.43, 7.1659 ],
[ 12003.41, 0.0164 ],
[ 12002.39, 23.4159 ],
[ 12001.38, 0.0284 ],
[ 12000.36, 0.0132 ],
[ 11999.34, 0.0194 ],
[ 11998.33, 0.0034 ],
[ 11997.31, 7.526 ],
[ 2445.72, 34.075 ],
[ 2445.17, 25.4842 ],
[ 2444.96, 0.1118 ],
[ 2444.75, 23.288 ],
[ 2444, 0.0247 ],
[ 2443.8, 0.192 ],
[ 765.51, 0.0828 ] ],
asks:
[ [ 12048.74, 2.523 ],
[ 12049.77, 0.0159 ],
[ 12050.79, 0.029 ],
[ 12051.82, 0.0061 ],
[ 12052.84, 0.0181 ],
[ 12053.87, 0.0164 ],
[ 12054.89, 0.0355 ],
[ 12055.92, 0.0042 ],
[ 13419.62, 0.0063 ],
[ 13420.64, 0.0174 ],
[ 13421.78, 0.0143 ],
[ 13422.92, 0.026 ],
[ 13424.06, 0.0055 ],
[ 13425.2, 14.4552 ],
[ 13426.23, 0.0065 ],
[ 13427.25, 0.0057 ],
[ 13428.39, 0.0147 ],
[ 13429.53, 4.0375 ],
[ 13430.56, 23.9541 ],
[ 13431.58, 0.0137 ] ],
timestamp: 1512845715447,
datetime: '2017-12-09T18:55:15.447Z',
mkt: 'LakeBTC',
pair: 'BTC/EUR',
ping: 0 }
So I guess that the problems I'm dealing with has to do with the asynchronous character of the function... but I'm not sure how I can make it synchronous.
Again, just to try to clarify my question: The objective is to get an array with 4 different types of object (one per pair --> array) so that I can operate on each.
Just to make it clearer, here's an illustration of what I'm trying to achieve:
[
[
Object1,
Object2,
Object3,
etc...
],
[
Object1,
Object2,
Object3,
etc...
],
[
Object1,
Object2,
Object3,
etc...
],
[
Object1,
Object2,
Object3,
etc...
]
]
Why is Promise.all returning the array without waiting on the requests'results?
I hope that was clear enough! If not let mw know! :P
Thanks in advance for your help!

Your test function does return a undefined. You need to return a promise for the result:
function test(p) {
return Promise.all(ccxt.exchanges.map(api => { //Looping through all the rest APIs
//^^^^^^^^^^^^^^^^^^
let exchange = new ccxt[api](); //Defining each API to make the requests
if (exchange.hasFetchOrderBook) {
return exchange //Beginning of the request
.fetchOrderBook(p)
.then(order => {
if (_.isObject(order) && order.bids[0][1]) {
let now = Math.floor(new Date());
order.mkt = exchange.name;
order.pair = p;
order.ping = now - order.timestamp;
return order; //Return the result of the request
}
// else undefined
})
.catch(e => {}); // undefined
}
// else undefined
}));
}
Of course your promises still fulfill with undefined when the if conditions do not apply or an error happens.

Related

Postman test extract integer variable from object of arrays

I am trying to create postman tests for an API.
The response I am getting from post man is in a json form. It looks like an Object of arrays.
{
"389": [
[
"2021-04-30T00:00:00Z",
16.130089309443093
]
],
"390": [
[
"2021-04-30T00:00:00Z",
14.899161948201808
]
],
"391": [
[
"2021-04-30T00:00:00Z",
17.495245579925736
]
],
"392": [
[
"2021-04-30T00:00:00Z",
16.78176061001777
]
],
"393": [
[
"2021-04-30T00:00:00Z",
25.473437964096448
]
],
"394": [
[
"2021-04-30T00:00:00Z",
56.746358310562826
]
],
"388": [
[
"2021-04-30T00:00:00Z",
18.49559245290604
]
]
}
I am trying to test the integer value that comes after the date is greater than 0 but cant seem to figure out how to traverse the structure in javascript.
With normal response Jsons they usually have the ID beside them and you can use that value, but not with this response
This is the test so far
pm.test("Check performance > 0", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.greaterThan(0);
});
It seems you are testing the whole JSON to be > 0. You should loop throught the values :
pm.test("Check performance > 0", function () {
var jsonData = pm.response.json();
Object.values(jsonData).forEach(record => {
pm.expect(record[0][1]).to.greaterThan(0);
});
/* record will be equal to
[
[
"2021-04-30T00:00:00Z",
16.130089309443093
]
]
and then
[
[
"2021-04-30T00:00:00Z",
14.899161948201808
]
]
and so on */
});
Object.values retrieves the values of a dictionary. See Object.values
(if we want the keys ["389", "390", ...] we can use Object.keys)

JSON Array.Reduce multidimensional

I'm trying to gathering an consolidated sum from this example:
[
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"income","id":"282","value":"3000000","opposite":"318"}
],
[
{"mode":"income","id":"280","value":"3000000","opposite":"316"}
]
]
In the previous sample we have duplicated values and the purposal y sum to compare with another objects in mode "income". Already try with loop but I have a headache in how to compare the outcome mode with income.
I hope to be clear with my question. Thanks.
You could run a nested for loop:
let data = [
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"outcome","id":"318","value":"1000000","opposite":"282"},
{"mode":"outcome","id":"316","value":"1000000","opposite":"280"}
],
[
{"mode":"income","id":"282","value":"3000000","opposite":"318"}
],
[
{"mode":"income","id":"280","value":"3000000","opposite":"316"}
]
];
let x = 0;
data.forEach(e => {
e.forEach(c => {
x = x + parseInt(c["value"])
})
});
console.log('SUM:', x);
Then, you extract the value of x to see the total "values"

How to get a specific array from a list of arrays

I want to get a specific array based on a code, the array is something like this:
const arr = [
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=11f18ac1-0476-4a1e-ada6-09e6566abc19",
1595619171842,
"0b7ad06f-7776-4bab-a8c6-53fd5fd5bd9b"
],
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=b64c143d-e817-434f-bf6f-0bd0e8d9e7b5",
1595619171844,
"2f44a130-71d9-47ce-b5d5-04587c3c81fc"
],
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=71dc5d26-75f4-4141-905e-074b0705eac4",
1595619171845,
"d7eb2a05-1f5a-48dd-b7ac-f3b071499d00"
],
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=d3645614-0ea3-4d17-80ab-57c6c6525fab",
1595619171846,
"940fb9a7-6fdd-4f8b-a808-26a9c60114bf"
]
];
How to I get the array with code "d7eb2a05-1f5a-48dd-b7ac-f3b071499d00"?
I was using reduce to get the more recent image, but now I have no idea!
Array#find returns the first elmenent of an array that returns true for the given function.
const specificArray = arr.find(subArray => {
return subArray[2] === "d7eb2a05-1f5a-48dd-b7ac-f3b071499d00";
}
Array#find (with destructuring) is best suited for this purpose.
const res = arr.find(([,,code])=>code==="d7eb2a05-1f5a-48dd-b7ac-f3b071499d00");
const arr = [
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=11f18ac1-0476-4a1e-ada6-09e6566abc19",
1595619171842,
"0b7ad06f-7776-4bab-a8c6-53fd5fd5bd9b"
],
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=b64c143d-e817-434f-bf6f-0bd0e8d9e7b5",
1595619171844,
"2f44a130-71d9-47ce-b5d5-04587c3c81fc"
],
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=71dc5d26-75f4-4141-905e-074b0705eac4",
1595619171845,
"d7eb2a05-1f5a-48dd-b7ac-f3b071499d00"
],
[
"https://firebasestorage.googleapis.com/v0/b/ziro-a…=media&token=d3645614-0ea3-4d17-80ab-57c6c6525fab",
1595619171846,
"940fb9a7-6fdd-4f8b-a808-26a9c60114bf"
]
];
const res = arr.find(([,,code])=>code==="d7eb2a05-1f5a-48dd-b7ac-f3b071499d00");
console.log(res);

Flatten an array grouped by nested elements in JavaScript

I have a tricky question... I have an array looks like this:
[
[ [ 'Attribute1', 'Attribute1Synonym1' ], [ 'Attribute2' ] ],
[ [ 'Attribute3' ] ],
[ [ 'Attribute2' ] ]
]
My result should be:
[
'Attribute1 Attribute2',
'Attribute1Synonym1 Attribute2',
'Attribute3',
'Attribute2'
]
The tricky thing is:
the result array has to grouped by the sub-sub-array
the crux is, the first index is an array(1) of arrays(2) of arrays(3)
and i would to like flatten the array by level 3 (array(3)) and at the result should be every possible combination between the upper level.
At level 2 (the first index) is an array with ('Attribute1' and 'Attribute1Synonym1')
so the result should be:
'Attribute1 Attribute2'
and
'Attribute1Synonym1 Attribute2'
the 'Attribute2' comes from the upper level
if the second index of level 2 ['Attribute2'] has also multiple indexes
for example ['Attribute2Synonym5']
the result should be:
'Attribute1 Attribute2'
'Attribute1Synonym1 Attribute2'
'Attribute1 Attribute2Synonym5'
'Attribute1Synonym1 Attribute2Synonym5'
and so on...
This works against your provided example, but I'm going to guess it's fragile against more complex arrays:
const deep = [ [ [ 'Attribute1', 'Attribute1Synonym1' ], [ 'Attribute2' ] ],
[ [ 'Attribute3' ] ],
[ [ 'Attribute2' ] ] ];
const flat = [];
deep.forEach(element => {
const left = element[0];
const right = element[1];
left.forEach(leftElement => {
if(right){
right.forEach(rightElement => {
flat.push(leftElement + ' ' + rightElement);
});
} else {
flat.push(leftElement);
}
})
});
Maybe like this:
var input_arr=[ [ [ 'Attribute1', 'Attribute1Synonym1' ], [ 'Attribute2' ] ],
[ [ 'Attribute3' ] ],
[ [ 'Attribute2' ] ] ];
var output_arr=[];
for(var key1 in input_arr){
var sub_input_arr=input_arr[key1];
for(var key2 in sub_input_arr){
var sub_sub_input_arr=sub_input_arr[key2];
for(var key3 in sub_sub_input_arr){
output_arr.push(sub_sub_input_arr[key3]);
}
}
}
console.log(output_arr);

for of loop is only run once

I need to traverse a pretty deep object and I need to extract 12 values in different depths. My plan was to extract with the for of the values for each depth but I have a problem in the first depth.
I am a little confused about the for of behavior.
I thought this:
for (const key of Object.keys(jsonData)){
console.log(i+1);
if (isWantedValue(key))
{
artifactColl[key] = jsonData[key];
}
console.log(key, jsonData[key]);
}
for of loop would run a cycle for each key element that it finds inside the object but the loop is only running once. It prints out all necessary keys with values in the lower console.log function but it calls isWantedValue function only once.
Can please somebody explain that to me?
Object looks like this:
{ searchNGResponse:
{ totalCount: [ '420' ],
from: [ '-1' ],
count: [ '-1' ],
tooManyResults: [ 'false' ],
collapsed: [ 'false' ],
repoDetails: [ [Object] ],
data: [ [Object] ] } }
console output:
1
called with searchNGResponse
searchNGResponse { totalCount: [ '416' ],
from: [ '-1' ],
count: [ '-1' ],
tooManyResults: [ 'false' ],
collapsed: [ 'false' ],
repoDetails: [ { 'xxx': [Object] } ],
data: [ { artifact: [Object] } ] }
Edit: updated
Your jsonData object has only one key, as the console output shows: searchNGResponse.
What you want is the keys of that object, the searchNGResponse object, specifically jsonData.searchNGResponse like this
for (const key of Object.keys(jsonData.searchNGResponse)){
console.log(i+1);
if (isWantedValue(key))
{
artifactColl[key] = jsonData.searchNGResponse[key];
}
console.log(key, jsonData.searchNGResponse[key]);
}

Categories