0

I take advantage of the first promise "crypto.model.find()" to store an array of "symbols" ( symbol[] ) from the DB and get some IDs I will use to create an URL to make a request to an API >>> axios.get(url)

In the second promise, I receive the answer from the API but I don't have acccess to my array symbol[].

I need both at this stage and I don't know how to do it.

I read about returning an array and pass it down the promises chain but in this case, I don't think I can use such an array : return [ axios.get(url), symbol[] ]

// getting coins description in my DB with Mongoose  
cryptoModel.find()                                                      
.then ( docsCrypto => {
        let coingeckoIDsRequest = '';                                   
        let symbol = [];  

// loop on the response from the DB
        docsCrypto.forEach( (eachCrypto) => {                           
// Filling the array of symbols from the DB
            symbol.push( eachCrypto.symbol )                            
// creating a chunk of the HTTPS API URL request with the IDs from the DB
            coingeckoIDsRequest += eachCrypto.coingecko_id + '%2C'      
        })

// URL creation
        let url = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&ids=' +
            coingeckoIDsRequest.substr(0, coingeckoIDsRequest.length-3) +
            '&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=24h%2C7d%2C30d%2C200d'      

// returning the API data   
        return axios.get(url)                                           
})
// !!! >>>>  I want to get to the next line with the data from the API AND the array "symbol[]" 
.then (res => console.log(res)) 
// if error > console.log       
.catch (err => console.log(err))
EstefanTT
  • 21
  • 5

3 Answers3

0

try declaring the symbol array outside the find function.

  • I thought about it but I wanted to limit as much as possible the use of variables in the main scope or context. It was the last thing I would try if no other existed. But I'm confident you solution would work ;) – EstefanTT May 21 '19 at 08:37
0

You can use Promise.resolve(your_variable) to create a new promise that immediately resolves as the variable value.

Then you can use Promise.all to combine them

I use setTimeout instead of the real axios in this example.

let variable = "value of a variable";

const axios = {
  get: () => new Promise(
    res => setTimeout(() => res('axios response'), 1000)
  )
}

Promise.all([
  axios.get(),
  Promise.resolve(variable)
]).then(
  resolved => console.log(resolved)
);
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • `variable` doesn't need to be Promise-wrapped. `Promise.all()` accepts raw values as well as promises. – Roamer-1888 May 20 '19 at 22:44
  • It looks like you and Roamer-1888 have a similar approach with slight differences. But it is the way, it works. Thank you for your help ^^ – EstefanTT May 21 '19 at 09:08
0

Simply use Promise.all() to aggregate the two members you wish to pass on. It doesn't matter that one is a Promise and the other is Array.

Judicious use of Array.prototype.map() avoids a lot of messing about.

cryptoModel.find()
.then(docsCrypto => {
    let symbols = docsCrypto.map(eachCrypto => eachCrypto.symbol);
    let url = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&ids=' +
        docsCrypto.map(eachCrypto => eachCrypto.coingecko_id).join('%2C') +
        '&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=24h%2C7d%2C30d%2C200d';
    return Promise.all([axios.get(url), symbols]);
})

In the next stage of the chain, destructuring provides a convenient way to access the two results.

.then(([axiosResult, symbols]) => {
    console.log(axiosResult);
    console.log(symbols);
});
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
  • I love how you simplify my forEach loop with map ! Your solution with Promise.all also works, it is perfect for what I needed. There is just a minor bug, there are ( ) missing in the destructured part. It is .then(([axiosResult, symbols]) instead of .then([axiosResult, symbols]. – EstefanTT May 21 '19 at 08:58
  • I also find another way to do it from another help I had on this matter. You can use return axios.get(url) .then (res => [res, symbols, amounts]) instead of Promise.all([axios.get(url), symbols]) I don't know which way is the best or the most correct. – EstefanTT May 21 '19 at 09:04
  • Aha, brackets, thank you. Must admit, i've not used that syntax much. Edited. – Roamer-1888 May 21 '19 at 11:07
  • Yes, the other way will work too. I wrote it both ways and decided (rightly or wrongly) that `Promise.all()` was better. The other way (as I wrote it) required a nested promise chain in order to retain access to `docsCrypto` or `symbols`. – Roamer-1888 May 21 '19 at 11:41
  • 1
    You are probably right, better to avoid nesting. It is, after all, one of the main benefits of promises. – EstefanTT May 21 '19 at 18:42