繁体   English   中英

如何构造一个 Promise,在其中调用异步函数,解析结果,然后解析/拒绝?

[英]How to construct a Promise that calls an async function inside of it, parses the result, and then resolves/rejects?

我想编写一个函数getUser() ,它返回一个 Promise ,它在resolve时传递用户对象,在reject时传递错误。 我正在使用 axios 提出请求。

这是我目前拥有的。

async function getUser() {

    try {
        const userResponse = await axios({
            method: 'post',
            url: "some_url",
            data: "some string data",
            headers: {
                'content-type': 'application/x-www-form-urlencoded'
            }
        });
        if (userResponse.data.status === 'success') {
            // resolve(validateResponse.data);
        } else {
            // reject(validateResponse.data);
        }
    } catch (error) {
        // reject(validateResponse.data);
    }

}

我想将整个try...catch块包装在Promise构造函数中,但 Promise 构造函数是new Promise((resolve, reject) => {...})而不是new Promise(async (resolve, reject) => {...}) 我知道我可以做后者,但这是一种反模式

Promise方法也不一定有效,因为当我使用getUser().catch()返回的Promise时出现任何错误,我不知道错误是否来自服务器的响应(状态不是'success' ) 或者如果请求本身失败。

解决这个问题的最安全方法是什么? 我知道有一个蛮力的解决方案,就是在不实际使用的情况下模仿Promise API,或者声明一个async Promise,但我觉得我每次都遇到了反模式。

感谢您的任何建议。

我将从概念上回答这个问题。

当您调用异步函数时,它会立即向调用该函数的代码范围返回一个承诺。

在异步函数内部,您不需要使用resolvereject 相反,您可以只使用returnthrow return就是承诺将解决的问题。 如果您throw ,这就是承诺将“拒绝”的内容。 尝试这样的事情:

async function getUser() {

    try {
        const userResponse = await axios({
            method: 'post',
            url: "some_url",
            data: "some string data",
            headers: {
                'content-type': 'application/x-www-form-urlencoded'
            }
        });
        if (userResponse.data.status === 'success') {
            return validateResponse.data;
        } else {
            throw new Error(validateResponse.data);
        }
    } catch (error) {
        throw error;
    }
}

在 async/await 出现后,我在处理 promise 时不再喜欢then语法。 为避免then ,请从异步函数的主体中调用getUser 如果您不是从异步函数的主体中调用getUser ,您将无法await它解析为的内容; 你将不得不使用then代替。 或者,您可以将该调用代码包装在立即调用的异步函数中,以便您确实可以使用await 这是我的代码(调用getUser )的粗略示例:

(async function()
{
    let user = await getUser();
    if(!user)
    {
        console.error(`Access Denied`);
        return;
    }
    // Rest of your code that should only run when you have a user goes here.
})();

我将上面的代码包装在一个立即调用的异步函数中的唯一原因是,我可以使用await而不是then来解决该承诺。

标有async函数旨在使用 promise .then()回调样式编写。 也就是说,为了解析一个值,你使用return关键字,为了拒绝一个值,你使用throw关键字。 因此,您的函数应编写如下:

async function getUser() {

    try {
        const userResponse = await axios({
            method: 'post',
            url: "some_url",
            data: "some string data",
            headers: {
                'content-type': 'application/x-www-form-urlencoded'
            }
        });
        if (userResponse.data.status === 'success') {
            return validateResponse.data;
        } else {
            throw new Error(validateResponse.data);
            // Alternately you can also just:
            // throw validateResponse.data
        }
    } catch (error) {
        throw new Error(validateResponse.data);
    }

}

Promise 方法也不一定有效,因为当我使用 getUser() 和 .catch() 返回的 Promise 时出现任何错误,我不知道错误是否来自服务器的响应(状态不是 'success ') 或者如果请求本身失败。

我会考虑以两种可检查的方式之一拒绝getUser内部的外部承诺 - 然后使用承诺拓扑调用getUser ,该拓扑将好的数据拆分为处理流(承诺链),并将错误拆分为另一个以进行区分。 例如:

  1. 创建一个名为 GetUserData 的数据包装器构造函数:

     const GetUserData = function( data) { this.data = data; }

    这可能会受益于为getUser参数值设置另一个参数。

  2. 删除try {catch() {}子句。 让 axios 错误抛出并拒绝getUser承诺。

  3. getUser返回“成功”的结果或抛出一个GetUserData对象:

     if (userResponse.data.status === 'success') { return userResponse.data; } else { throw new GetUser( userResponse.data); }
  4. 使用区分错误类型的拓扑调用getUser

     let userPromise = getUser(); // parameterized? userPromise.then(data => { do something with user data}); // chain promises on "success" as needed // split errors into a .then handler for server errors and a .catch handler for axios errors: userPromise.catch( something => { if( something instanceOf GetUserData) { return something.data; } throw something; // rethrow axios error }) .then ( data => { deal with unsuccessful server data}) .catch( error => { deal with axios error })

暂无
暂无

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

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