简体   繁体   English

在没有异步功能的情况下等待响应?

[英]Await response without Async Function?

Is it possible to, in a function, wait for the response from an asynchronous function, without making the entire function asynchronous, ala await without async, or something similar?是否可以在函数中等待异步函数的响应,而不使整个函数异步,ala await 没有异步,或类似的东西? An example of this:这方面的一个例子:

const axios = require('axios');
const converter = require('number-to-words');
const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
});
function dataFetch() {
    //fetches current exchange rate of NOK to USD
    let data = await axios.get('https://api.exchangeratesapi.io/latest?base=NOK');
    //fetches current value of Norwegian Oil fund
    let res = await axios.get('https://www.nbim.no/LiveNavHandler/Current.ashx');
    //extracts value of Norwegian Oil Fund from response data, and converts it to USD in real time.
    let dolla = (res.data.Value.replace(/\s/g, '') * data.data.rates.USD).toFixed(2);
    //Converts Basic number to number with commas, and a dollar sign.
    let val = formatter.format(dolla);
    //Generates word format of number(i.e. one hundred instead of 100)
    let str = converter.toWords(dolla);
    //Generates word format of cents.
    let cents = converter.toWords(dolla.split('.')[1].substring(0, 2));
    //Returns JSON of commaed value and full word string
    return {num: val, word: `${str} dollars and ${cents} cents`};
}
console.log(dataFetch().val);

I want to make sure that the value returned by dataFetch() is the processed version of the data received from the get request, rather than a promise, or null so that the console.log() prints out the value of the fund in dollars, rather than undefined, or null, or something else.我想确保dataFetch()返回的值是从 get 请求收到的数据的处理版本,而不是承诺,或者 null 以便console.log()以美元打印出基金的价值, 而不是 undefined, 或 null, 或其他东西。

There is almost certainly an easy solution to this, but I cannot seem to find it, and it has been breaking the code I have been working on for a while.几乎可以肯定有一个简单的解决方案,但我似乎找不到它,而且它已经破坏了我已经工作了一段时间的代码。

Update : Updated to add context for the problem.更新:更新以添加问题的上下文。 I apologize for my slightly unclear comments.我为我稍微不清楚的评论道歉。

You are making multiple asynchronous (axios) calls inside your dataFetch() function.您正在dataFetch()函数内进行多个异步 (axios) 调用。 That means that your function will return BEFORE any of those asynchronous operations are complete and there is nothing you can do about that.这意味着您的函数将在任何这些异步操作完成之前返回,您对此无能为力。 That's how asynchronous operations work in Javascript.这就是异步操作在 Javascript 中的工作方式。 As such, you cannot return the final value from your function.因此,您无法从函数中返回最终值。 Your function returns before that final value is known.您的函数在最终值已知之前返回。

There are three options for communicating back the final value:有三个选项可以返回最终值:

  1. Promise承诺
  2. Callback打回来
  3. Event事件

Pick one of those.选择其中之一。

In this case, the natural fit would be a promise.在这种情况下,自然契合将是一个承诺。 You have to declare your dataFetch() function as async anyway so your calls to await in it will be allowed.无论如何,您必须将dataFetch()函数声明为async函数,以便您在其中调用await将被允许​​。 That means that it will already return a promise automatically.这意味着它已经自动返回了一个承诺。 Then to get the value from dataFetch() , you use either await or .then() on the returned promise:然后要从dataFetch()获取值,您可以在返回的承诺上使用await.then()

dataFetch().then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
});

This is how asynchronous programming works in Javascript.这就是异步编程在 Javascript 中的工作方式。

Utilizing the answer I had received, this is the code I went with:利用我收到的答案,这是我使用的代码:

function bimFetch() {
    axios.get('https://api.exchangeratesapi.io/latest?base=NOK').then(data => {
        axios.get('https://www.nbim.no/LiveNavHandler/Current.ashx').then(res => {
            let dolla = (res.data.Value.replace(/\s/g, '') * data.data.rates.USD).toFixed(2);
            let val = formatter.format(dolla);
            let str = converter.toWords(dolla);
            let cents = converter.toWords(dolla.split('.')[1].substring(0, 2));
            if(dolla.split('.') === '01')
                currentStatus = { num: val, word: `${str} dollars and ${cents} cent` };
            else
                currentStatus = { num: val, word: `${str} dollars and ${cents} cents` };
        });
    });
}

Once both of the fetches and the formatting is complete, then it outputs its response to currentStatus .一旦获取和格式化都完成,它就会将其响应输出到currentStatus I set a setTimeout() , which after waiting about 5 seconds will send a message with the updated status over all the connected WebSockets.我设置了一个setTimeout() ,等待大约 5 秒后,它将通过所有连接的 WebSockets 发送带有更新状态的消息。

I would like to thank @jfriend00 for their help on this problem, as I have learned a valuable lesson in JS asynchronous coding.我要感谢@jfriend00 在这个问题上的帮助,因为我在 JS 异步编码中学到了宝贵的一课。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM