【问题标题】:How can I use async/await in 'new Promise' block to fetch data from an api?如何在“new Promise”块中使用 async/await 从 api 获取数据?
【发布时间】:2021-02-20 01:38:38
【问题描述】:

我无法在引发await is only valid in async function 错误的“新承诺”块内使用异步/等待。我不知道它是否可能,但我需要使用它或一种方法来实现我想要的。这是我正在尝试做的事情:

用户键入一个查询,它通过一个名为doesExistrecursive function。我必须使用递归函数,因为 API 并不总是为查询提供数据。递归函数会尝试 3 次,也就是说,它会发送 3 次 api 请求来获取数据,然后返回错误消息“无法获取数据”。在函数中,我返回一个新的承诺,因为我必须从那里发出 api 请求。

为了获取数据,我之前使用了 request,但现在我想将 axios 与 async/await 一起使用。那么如何在 new Promise 块内使用 axios 和 async/await 呢?

这是request的代码:

router.get('/example', async (req, res) => {

        try{
            const query = 'Superman';
            const data  = await doesExist(query);
    
            if(!data) {
                console.log('No data');
            }
    
            res.render('../views/example', { data, query });
        }catch(err) {
            console.log(err);
        }
        
});
    
    
const doesExist = (query, retries = 0) => {

        const url           = `http://api.example.com/json?fields=${query}`;
        const maxRetries    = 3;
    
        return new Promise(( resolve, reject ) => {
            
            const retry = () => {
                if (retries < maxRetries) {
                    resolve(doesExist(query, retries + 1));
                } else {
                    reject(`Could not get the data after ${retries} retries.`);
                }
            };
    
            request(url, function (error, response, body) {
                if (!error && response.statusCode === 200) {
                    const data = JSON.parse(body);
                    resolve(data);
                } else {
                    retry();
                }
            });
       });
}; 

这就是我尝试使用async/await 引发的错误:

const doesExist = async (query, retries = 0) => {

        const url           = `http://api.example.com/json?fields=${query}`;
        const maxRetries    = 3;
    
        return new Promise(( resolve, reject ) => {
            
            const retry = () => {
                if (retries < maxRetries) {
                    resolve(doesExist(query, retries + 1));
                } else {
                    reject(`Could not get the data after ${retries} retries.`);
                }
            };

            const data = await axios.get(url);

            if(data.statusCode === 200) {
                resolve(data);
            }else{
                retry();
            }
     
       });
}; 

如果不能在 promise 块中使用 async/await,那么请告诉我如何实现它。谢谢

【问题讨论】:

  • 你试过new Promise(async ( resolve, reject ) =&gt; {吗?
  • @Anatoly 不,我刚做了。它似乎正在工作。非常感谢。将其发布为答案。

标签: javascript node.js promise async-await axios


【解决方案1】:

Never pass an async function as the executor to new Promise!如果你想使用async/await 和已经返回承诺的axios,你不需要——也不应该使用——Promise 构造函数到promisify a callback API。随便写

async function doesExist(query, retries = 0) {
    const url           = `http://api.example.com/json?fields=${query}`;
    const maxRetries    = 3;

    const data = await axios.get(url);

    if (data.statusCode === 200) {
       return data;
    } else if (retries < maxRetries) {
       return doesExist(query, retries + 1);
    } else {
       throw new Error(`Could not get the data after ${retries} retries.`);
    }
}

【讨论】:

  • 非常感谢。但是,我还有另一个问题。假设我必须在 dosExist 函数中做更多的错误处理,除了抛出你使用的新错误。我应该在这个函数中执行此操作,还是将其留给端点中的 try/catch 块执行?
  • @Zak 取决于这些错误是否会通过重试(增加 retries 计数)来处理
  • 没有。假设我必须在第一个 if 块而不是 return data 中对不同的端点进行另一个 api 调用。现在这个新调用的错误应该在 router.get 部分的 try/catch 块中处理?
  • 没有一般原则。这些错误可以由doesExist 处理,仍然向调用者返回合理的结果吗?然后你会在doesExist 中处理它们。如果您无法处理它们,则抛出异常(即拒绝返回的承诺)。
  • @BryanGrace 如果您参考我的第一句话,那实际上是通用的。真的没有例外。
【解决方案2】:

promise 调用的函数必须是这样的“异步”函数。

new Promise (async (Resolve) => {
    await new Promise (async (_Resolve) => {
         console.log ("A");
         _Resolve ();
    });

    console.log ("B");
    Resolve ();
}); 

【讨论】:

  • 承诺中的承诺?我不明白。
  • axios.get(url);返回一个承诺。
猜你喜欢
  • 2019-04-07
  • 2020-09-09
  • 2020-12-02
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 2018-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多