【问题标题】:How to pass a variable AND an API response to the next promise (.then) [duplicate]如何将变量和 API 响应传递给下一个承诺(.then)[重复]
【发布时间】:2019-05-20 21:19:18
【问题描述】:

我利用第一个承诺“crypto.model.find()”从数据库中存储一个“符号”数组 (symbol[]) 并获取一些 ID,我将使用这些 ID 创建一个 URL 来发出请求到 API >>> axios.get(url)

在第二个承诺中,我从 API 收到了答案,但我无法访问我的数组符号 []。

现阶段我都需要,但我不知道该怎么做。

我读到了关于返回一个数组并将其传递到 Promise 链的内容,但在这种情况下,我认为我不能使用这样的数组: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))

【问题讨论】:

    标签: javascript promise chaining


    【解决方案1】:

    只需使用Promise.all() 来聚合您希望传递的两个成员。一个是 Promise 一个是 Array 没关系。

    明智地使用Array.prototype.map()可以避免很多麻烦。

    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]);
    })
    

    在链的下一个阶段,destructuring 提供了一种方便的方式来访问这两个结果。

    .then(([axiosResult, symbols]) => {
        console.log(axiosResult);
        console.log(symbols);
    });
    

    【讨论】:

    • 我喜欢你用 map 简化我的 forEach 循环的方式!您使用 Promise.all 的解决方案也适用,非常适合我的需要。只有一个小错误,解构部分中缺少 ( )。它是 .then(([axiosResult, symbols]) 而不是 .then([axiosResult, symbols].
    • 我还从我在这件事上获得的另一个帮助中找到了另一种方法。您可以使用 return axios.get(url) .then (res => [res, symbols, amount]) 而不是 Promise.all([axios.get(url), symbols]) 我不知道哪种方式是最好的或最正确的。
    • 啊哈,括号,谢谢。必须承认,我没有太多使用这种语法。已编辑。
    • 是的,其他方式也可以。我以两种方式都写了它,并决定(正确或错误地)Promise.all() 更好。另一种方式(如我所写)需要一个嵌套的承诺链,以保留对docsCryptosymbols 的访问。
    • 你可能是对的,最好避免嵌套。毕竟,这是 Promise 的主要好处之一。
    【解决方案2】:

    尝试在 find 函数之外声明符号数组。

    【讨论】:

    • 我想过,但我想尽可能地限制变量在主作用域或上下文中的使用。如果没有其他存在,这是我会尝试的最后一件事。但我相信你的解决方案会奏效;)
    【解决方案3】:

    您可以使用Promise.resolve(your_variable) 创建一个立即解析为变量值的新承诺。

    那么你可以使用Promise.all来组合它们

    在本例中,我使用setTimeout 而不是真正的axios

    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)
    );

    【讨论】:

    • variable 不需要被 Promise 包装。 Promise.all() 接受原始值和承诺。
    • 看起来您和 Roamer-1888 的方法相似,但略有不同。但这就是方式,它有效。谢谢你的帮助^^
    猜你喜欢
    • 2017-07-16
    • 1970-01-01
    • 2018-07-03
    • 2018-01-06
    • 1970-01-01
    • 2013-06-19
    • 2020-01-06
    • 2017-11-28
    • 2016-01-21
    相关资源
    最近更新 更多