首页 > 解决方案 > JavaScript 异步函数问题

问题描述

假设我有一个 Web 应用程序返回给定货币对/exchange_rate/ccy1/ccy2的汇率,只要在数据库中找不到该货币对,Web 应用程序就会返回 404。

在前端 JavaScript 代码中,为了安全起见,每当本地汇率查询失败时,我都会查询公共提供商,比如 currencyconverterapi.com

我们也假设由于某种原因(实际代码使用 Vue 生命周期钩子),全局变量rate,并且两个函数不能合并,不能做成 async

以下代码的问题是它仅在本地查询axios.get('/exchange_rate/EUR/' + ccy)解决时才有效;当它拒绝时,将在集合amount * rate之前执行——axios.get('http://free.currencyconverterapi.com...)rate

var rate;

function getExchangeRate(ccy) {
    return axios.get('/exchange_rate/EUR/' + ccy)
    .then(ret => {
        rate = ret.data.rate;
    }).catch(err => {
        axios.get('http://free.currencyconverterapi.com/api/v5/convert?q=EUR_' 
        + ccy).then(ret => {
            rate = ret.data.results.val;
        });
    });
}

function toEUR(ccy, amount) {
    getExchangeRate(ccy)
    .then(() => {
        return amount * rate;
    });
}

var EURAmount = toEUR('USD', 42);

我的问题是:有没有办法保证inrate正确设置?getExchangeRatetoEUR

标签: javascriptasynchronouspromise

解决方案


then您的函数toEUR中的 没有等待第二个请求完成,因为您没有returncatch.

您也不应该对rate变量使用共享状态。只需将其作为您的承诺的结果返回即可。

function getExchangeRate(ccy) {
    return axios.get('/exchange_rate/EUR/' + ccy)
    .then(ret => ret.data.rate)
    .catch(err => {
        return axios.get('http://free.currencyconverterapi.com/api/v5/convert?q=EUR_' 
        + ccy)
            .then(ret => ret.data.results.val);
    });
}

function toEUR(ccy, amount) {
    return getExchangeRate(ccy)
        .then(rate => amount * rate);
}

toEUR('USD', 42)
    .then(amount => console.log(amount))
    .catch(err => console.error(err));

我建议将备份调用分解为一个单独的函数,这样你就没有嵌套的承诺:

function getExchangeRatePublicProvider(ccy) {
    return axios.get('http://free.currencyconverterapi.com/api/v5/convert?q=EUR_' 
        + ccy)
        .then(ret => ret.data.results.val);
}

function getExchangeRate(ccy) {
    return axios.get('/exchange_rate/EUR/' + ccy)
        .then(ret => ret.data.rate)
        .catch(err => getExhangeRatePublicProvider(ccy));
}

function toEUR(ccy, amount) {
    return getExchangeRate(ccy)
        .then(rate => amount * rate);
}

toEUR('USD', 42)
    .then(amount => console.log(amount))
    .catch(err => console.error(err));

推荐阅读