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

时间:2020-01-27 01:51:55

标签: javascript node.js promise

我想编写一个函数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) => {...})。我知道我可以做,但是it's an anti-pattern

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

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

谢谢您的建议。

3 个答案:

答案 0 :(得分:2)

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

当您调用异步函数时,它会立即将诺言返回给调用该函数的代码范围。

除了异步功能外,您无需使用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;
    }
}

异步/等待出现后,在处理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来解决该承诺。

答案 1 :(得分:1)

标记为bool myEntry::search(Node *root, char *target) { myEntry::Node *currentNode = new myEntry::Node; currentNode = root; while(*target != '\0') { if((*target-97)== -53) myEntry::index = 27; else { myEntry::index = *target++ - 97; } if(!currentNode->forward[myEntry::index]) return false; currentNode = currentNode->next[myEntry::index]; } return (currentNode->correct); } 的函数应使用promise async回调样式编写。也就是说,为了解析一个值,您使用.then()关键字,并且为了拒绝一个值,您使用return关键字。因此,您的函数应编写如下:

throw

答案 2 :(得分:1)

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

我将以两种可检查的方式之一来查看拒绝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 })
    
相关问题