【问题标题】:Multiple awaits inside one async function一个异步函数中的多个等待
【发布时间】:2022-03-10 20:14:55
【问题描述】:

我有一个包含 3 个等待的 async 函数,如下所示:

const sequenceOfCalls = async(req, res, next) =>{
   await mongoQuery();
   await apiCall1();
   await apiCall2(); 
}

apiCall1 使用mongoQuery 的响应,apiCall2 使用apiCall1 的响应。

问题是apiCall2 工作不正常(我已经验证了apiCall2 的所有入口参数和apiCall1 的响应)。

可能存在什么问题?请帮忙,因为我已经被困了好几个小时了。

如果你想看代码,我之前发过this post

编辑
我会尽量做到最具描述性和清晰性。
API 相关信息:
我有一个名为 KATM 的 API(仅响应授权的 IP 地址)
他们提供了一份报告,为了获得该报告,我需要执行 3 个步骤:
1) 使用 Claim_id 注册客户
2) 使用之前注册的 Claim_id 发送报告请求。这会以 Token
3)使用提供的令牌。这终于提供了一份报告。
源代码信息:
我如何注册用户: export.register = async(req, res, next) => { const body = req.body;

    /* 1. Searching for client in database */
    const client = await Katm_client.findOne({
        name: body.name,
        family_name: body.family_name,
        patronymic: body.patronymic,
    });

    /* 2. If client exists in database */
    if (client) {
        return res.status(500).json({ message: "Client already registered" });
        // throw new Error("Client already exists");//return...ns
    }

    /* 3. If client does not exist in database, create a Client object that will be passed to mongo Model and KATM */
    client_object = {
        claim_id: nanoid(20),
        claim_date: moment().format("DD.MM.YYYY"),
        claim_number: Math.random().toFixed(10).replace("0.", ""),
        agreement_date: moment().format("DD.MM.YYYY"),
        agreement_number: Math.random().toFixed(10).replace("0.",""),
        family_name: body.family_name,
        name: body.name,
        patronymic: body.patronymic,
    };
    const new_client = new Katm_client(client_object)

    /* 4. Make a call to KATM api with Client object */
    const katm_registration = await axios.post(
        'http://10.22.50.3:8000/inquiry/individual',
        {
            header:{ 
                type: "B",
                code: "00433"
            }, 
            request: client_object
            
        },
        {
            headers: {
            'content-type': 'application/json'
            }
        }
        
    );

    /* 5. Handling response from the api */
    if(katm_registration.data.result.code == "05000" && katm_registration.data.result.message == "Успешно"){
        const savedClient = await new_client.save();
        return res.status(200).json({ message: 'Client registered and saved in database.', client: new_client});
    }else{
        return res.status(500).json({ message: katm_registration.data });
    }

接下来我使用一个模块来获取令牌,然后使用它来获取这样的报告:

exports.get_report_credit_info = async(req, res, next) => {
    const body = req.body;

    /* 1. Searching for client in database (Full name is used, but can be changed)*/
    const client = await Katm_client.findOne({
        name: body.name,
        family_name: body.family_name,
        patronymic: body.patronymic
    });

    if (!client) {
        return res.status(401).json({ message: "Client is not registered" });
    }

    /* 2. If client was found in database, make first API call */
    let credit_report;
    try{
        credit_report = await axios.post(
            'http://10.22.50.3:8001/katm-api/v1/credit/report',
            {
                security: {
                    pLogin: 'm',
                    pPassword: 'io',
                },
                data: {
                    pHead: "005",
                    pCode: "00433",
                    pLegal: 1,
                    pClaimId: client.claim_id,
                    pReportId: 8,
                    pReportFormat: 1
                }
            },
            {
                headers: {
                'content-type': 'application/json'
                }
            }
        );
    }catch(err){
        return res.status(400).json({errorMessage: err.message})
    }
    if(!credit_report.data.data.token) return res.status(400).json({message: credit_report.data});
    /* 2. Second API call to get Report */
    status_data = {
        pHead: "005",
        pCode: "00433",
        pToken: credit_report.data.data.token,
        pClaimId: client.claim_id,
        pReportFormat: 1
    }
    console.log(status_data)
    let credit_report_status;
    try{
        credit_report_status = await axios.post(
            'http://10.22.50.3:8001/katm-api/v1/credit/report/status', { data: status_data },
            {
                headers: { 'content-type': 'application/json' }
            }
        );
    }catch(err){
        return res.status(400).json({errorMessage: err.message})
    };
    if(credit_report_status.data.data.result == '05000') return res.status(200).json({ message: 'Client fetched.', clientData64: credit_report_status.data.data.reportBase64});
    else return res.status(400).json({message: credit_report_status.data})
};

我尝试过的:
我分离了第二个 await(credit_report_status) API 调用来获取报告并且它工作了,但是一旦我添加了第二个 await(credit_report_status) API 调用,它就不再工作了。
我得到一个令牌,这意味着首先 await credit_report 工作正常。我假设第二个 await(credit_report_status) 没有通过或什么
如您所见,我将 (credit_report_status) 的入口参数存储为对象,然后将其传递给 Axios。我将其注销以确保它具有正确的信息。
问题是第二个(最后一个)等待(承诺)在 15 次中工作了 1 次。 API 没有任何问题,因为我经常用 Postman 检查它

【问题讨论】:

  • 目前你没有发布没有给出你的问题的完整和可重现的例子。确保您的问题是独立的,并包含其他人帮助您所需的所有信息。
  • @Webber,我不知道该怎么做,因为所使用的 API 不能被公众访问。
  • 你是说apiCall2的参数没问题,所以函数实际上在apiCall1之后接收到了正确的数据。如果我的理解是正确的,那么与调用顺序无关,问题出在 apiCall2 内部。此外,您的示例代码不正确:因为没有传递参数。
  • @slkorolev,有参数传递。 1) mongoQuery() 检索客户端和 client.claimId 被传递给 apiCall1()“PClaimId 参数”。 2) client.claimId 和 token(从 apiCall1() 的响应中检索) 被传递给 apiCall2() “pToken: credit_report.data.data.token”。另外,我尝试在单独的模块中使用 await apiCall2() 并且它运行良好
  • 您能否更新您的问题,以便具体说明 api、api 调用和参数?就目前而言,没有足够的信息来解决这个问题。所有信息都应该在问题内,而不是在链接后面。

标签: javascript node.js async-await promise


【解决方案1】:

上下文

正如您所说,调用中的实现对您不可用,您有两种选择。

第一

您可以围绕调用创建一个 try catch 块,并输出调用可能引发的任何错误。

const sequenceOfCalls = async(req, res, next) =>{
  try {
    await mongoQuery();
    await apiCall1();
    await apiCall2(); 
  } catch (error) {
    // do something with the error, so that you can see it
    console.log(error)
    res.status(400).send('An unexpected error occurred')
  }

  next();
}

第二

如果错误描述性不够,并且您需要知道另一端发生了什么,那么您唯一的选择是联系您正在调用的 API 的维护者。

【讨论】:

  • 没有错误。并且 API 工作正常,因为我已经在 Postman 上测试了这两个调用并且它们确实有效。我刚才注意到 apiCall2 在模块中被隔离时可以工作,但是一旦我将 apiCall1 和 apiCall2 结合起来,那么 apiCall2 就会停止工作
  • 你说的是“不工作”,但如果它也没有给出响应并且它也没有给你一个错误,那么这是模棱两可的。你说邮递员工作并给你输出。尝试将其与您从正在调试的调用中获得的输出进行比较。
猜你喜欢
  • 2017-01-15
  • 2021-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多