繁体   English   中英

使用异步与返回新的区别 Promise

[英]difference using async vs return new Promise

我试图从 NextJS API 页面调用异步实用程序 function,但未定义。 当我 go 到 localhost:300/api/hello 时控制台打印如下

result =  undefined

文件一:api/hello.js

export default function handler(req, res) {
  getCountries().then(result=>{
    console.log('result = ', result);
    res.status(200).json({ status: 'ok', data: result.data });
  }).catch(err=>{
    console.log('error = ', err);
    res.status(500).json({ status: 'error', error: err });    
  })
}

文件 2:utils/getCountries.js

const getCountries = async () => {
    var response = [];
    var params = { action: "get_countries", ...authKey }
    axios.get(APIFOOTBALL_URL, { params: params })
        .then((result) => {
          response = [...result.data];
          return response;
        }).catch((err) => {
            throw err;
        });
}

export default getCountries;

将 getCountries function 更改为以下工作,但我不明白为什么。 异步不也返回 promise 吗? 如果非要写在async/await方法中,我应该怎么写go呢?

文件 2:utils/getCountries.js

const getCountries = () => {
    return new Promise((resolve, reject) =>{
        var response = [];
        var params = { action: "get_countries", ...authKey }
    
        axios.get(APIFOOTBALL_URL, { params: params })
            .then((result) => {
              response = [...result.data];
              resolve(response);
            }).catch((err) => {
                reject;
            });
    })
}

getCountries的第一个示例中,您返回的是 promise 的空值(未定义),而在第二个示例中,您返回的是 promise 的响应。

在您的第一个示例中发生的情况是axios.get运行,但是没有什么能真正阻止 function 返回。 axios.get上调用.then的全部目的是为了在 promise 解决后执行.then回调中的任何内容。 否则,您可以像往常一样在axios.get调用.then之后编写您正在编写的代码,如果您使用 await,您可以这样做。 使用await会停止代码执行,直到 promise 被解决或拒绝(这就是为什么你应该只在 try-catch 块中使用await

如果你的第一个例子重构如下:

const getCountries = async () => {
    const params = { action: "get_countries", ...authKey }
    try {
        const result = await axios.get(APIFOOTBALL_URL, { params: params });
        const response = [...result.data];
        return response;
    } catch (err) {
        console.error("An error occurred while trying to fetch countries: ", err);
        throw err;
    }
}

您最终会在axios.get调用之后阻止代码的执行,直到 promise 被解决或拒绝。

简而言之,您的第一个示例不起作用的原因是因为您的 function 在axios.get调用之后返回undefined (隐含地因为您的第一个示例中没有 return 语句)。 没有什么能阻止它返回,因此您的第一个示例返回的 promise 总是用undefined的值解析。

您的第二个示例之所以有效,是因为当您手动返回 promise 时,它始终处于待处理状态,直到您使用resolve(response); reject

如果这没有帮助,请这样考虑 -> 在调用代码中,当您执行getCountries.then时, .then部分仅在解析 promise 时执行。 它解析的值被传递给回调(您用作result )。 在您的第一个示例中, getCountries立即解析为undefined的值,因此您的回调获取undefined的值,而在第二个示例中, getCountries返回的 promise 待处理,直到在您的代码中调用resolve ,这仅在您的 API 请求之后发生promise 解析(因为您在axios.get .then中调用它)。

另外,在您的第一个示例中,当您return response; axios.get .then ,您从 .then 的回调.then返回。 这不会从getCountries function 返回。也许这让您认为这应该有效,但实际上无效。

如果你这样做,你的第一个例子也可以工作:

const getCountries = async () => {
    const params = { action: "get_countries", ...authKey }
    return axios.get(APIFOOTBALL_URL, { params: params })
        .then((result) => {
          const response = [...result.data];
          return response;
        }).catch((err) => {
            throw err;
        });
}

因为现在, getCountries正在返回一个 promise 的响应,而不是仅仅返回一个 promise 的undefined

最后,正如@jfriend00 提到的,没有理由让.catch()再次抛出错误。 catch 的目的是处理错误(记录或处理错误)。 您现在使用.catch()的方式将具有与根本不使用它相同的行为。

async function 中,您必须await您的 promise 或必须返回它。 如果没有其中之一,实际上没有什么会等待 promise 或从中返回任何结果。 由于使用async的目的是为了能够使用await ,下面是它的样子:

const getCountries = async () => {
    const params = { action: "get_countries", ...authKey }
    const result = await axios.get(APIFOOTBALL_URL, { params: params });
    return result.data;
}

或者,您可以只返回 promise 而不需要async

const getCountries = () => {
    const params = { action: "get_countries", ...authKey }
    return axios.get(APIFOOTBALL_URL, { params: params }).then(result =>{
        return result.data;
    });
}

关于您的代码的其他一些注意事项:

  1. 没有理由再使用var了。 在所有现代 Javascript 中使用letconst代替。
  2. 没有理由用response = [...result.data]; . 你可以做return result.data
  3. 您的最后一个代码块被认为是 promise 反模式。 你永远不想用手动创建的 promise 包装现有的 promise(从axios.get()调用返回的那个)。这只是没有必要,而且经常会产生错误处理问题,而你确实有错误处理,因为你没有调用reject(err)正确。
  4. 没有理由让.catch()throw err ,除非您在该.catch()中还有一些其他代码(例如记录错误)。

暂无
暂无

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

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