如何解决Promise Never Resolve 使用 Axios
我正在使用 Wdio 并定义一个客户报告器以与 testrails api 集成。计划是使用 axios 在测试钩子内发出这些请求。
不幸的是,我无法让 axios 返回任何关于请求的有效数据。在大多数情况下,当我们 await
响应时,线程会完全停止执行而没有任何日志输出。如果我把它弄得足够好,有时我可以让它返回一个未解决的承诺,但我无能为力最终解决这个承诺。
此外,在我的所有尝试中,testrails 都没有收到请求(我也测试了其他一些网址,我很确定问题不在目的地)。
我已确保网络访问和安全性不是因素。我们还尝试使用 axios 帖子和直接的 axios() 方法,但没有成功。
我将复制下面的文件,我已经添加了大约十几个尝试/配置,并在每个尝试/配置上附上了关于我们得到什么的注释。问题的关键在于 addRun() 方法。
在大多数情况下,我们似乎从未解决过承诺。有一个例外,我们根本不与响应交互,只需登录 then() 语句即可。如果我们这样做,我们可以看到那些日志,但是 axios 调用的结果永远不会生效(运行不是在 testrails 中创建的)。
const WdioReporter = require('@wdio/reporter').default
const axios = require('axios').default;
module.exports = class TestrailsReporter extends WdioReporter{
constructor(options) {
/*
* make reporter to write to the output stream by default
*/
options = Object.assign(options,{ stdout: true })
super(options)
}
// I have tried marking this as both async and not,no difference
async onRunnerEnd(suite) {
console.log("CHECKPOINT RUNNER END")
this.recordResults(caseIds[5],results[5],'renters api tests',5);
}
/**
* takes the results from a test suite and records them in testrails
* @param suiteId -- the suite defined in the testrails project
* @param projectId -- the project id defined in the testrails project
* @param caseIds -- a list of cases with which to create the test run
* @param results -- a list of case:result pairings
*/
async recordResults(caseIds,results,name,projectId) {
console.log(`CHECKPOINT RECORDING RESULTS ${projectId}`)
let testRun = await this.addRun(results['suiteId'],caseIds['cases'],projectId);
testRun.then(console.log)
await this.addResults(testRun,results['cases']);
}
async addRun(suiteId,caseIds,name = '',projectId) {
console.log("CHECKPOINT ADD RUN")
let addrunconfig = {
method: 'post',url: `https://REDACTED.testrail.io/index.PHP?/api/v2/add_run/${projectId}`,headers: {
'Content-Type': 'application/json',Authorization: token,Cookie: 'tr_session=041c4349-688f-440a-95a3-afc29d39320a'
},data: JSON.stringify({
suite_id: suiteId,include_all: false,case_ids: caseIds,name: name
})
};
// let x = axios.get('https://www.google.com/')
// console.log(x)
axios.defaults.timeout = 1000;
// THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT,RETURNS PENDING PROMISE TO RESPONSE
// let response = axios(addrunconfig)
// .then(function (response) {
// console.log("WHAAAT?")
// return response.data.id;
// })
// .catch(function (error) {
// console.log("HELP!")
// console.log(error);
// });
// THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT,NO LOGGING APPEARS AFTER
let response = await axios(addrunconfig)
.then(function (response) {
console.log("WHAAAT?")
return response.data.id;
})
.catch(function (error) {
console.log("HELP!")
console.log(error);
});
// THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT
// await axios.post(`https://REDACTED.testrail.io/index.PHP?/api/v2/add_run/${projectId}`,addrunconfig)
// .then(
// function (response){
// console.log('WHAAAT?')
// console.log(response)
// console.log('NO WAY?')
// })
// THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT,BUT RETURNS A PENDING PROMISE TO RESPONSE
// let response = axios.post(`https://REDACTED.testrail.io/index.PHP?/api/v2/add_run/${projectId}`,addrunconfig)
// .then(
// function (run){
// console.log('WHAAAT?')
// console.log(run)
// console.log('NO WAY?')
// })
// THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT,addrunconfig)
// .then(
// function (run){
// console.log('WHAAAT?')
// })
// THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT,addrunconfig)
// .then(run => {
// console.log('WHAAAT?')
// })
// THIS EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT,BUT NOT AFTER
// let response = await axios.post(`https://REDACTED.testrail.io/index.PHP?/api/v2/add_run/${projectId}`,addrunconfig)
// .then(console.log('WHAAAT?'))
// THIS EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT,AND AFTER
// let response = axios.post(`https://REDACTED.testrail.io/index.PHP?/api/v2/add_run/${projectId}`,addrunconfig)
// .then(console.log('WHAAAT?'))
// EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT,nothing FROM THE CATCH,AND nothing AFTER
// const response = await axios(addrunconfig).then(console.log("HI")).catch(function (error) {
// console.log("HELP!")
// console.log(error);
// });
console.log("ANYTHING")
console.log(response)
return response
}```
解决方法
想通了,这是 WDIOReporter 父类不能很好地处理来自 axios 的异步调用。解决方案在这里找到: https://github.com/webdriverio/webdriverio/issues/5701
,您是否尝试过使用
await axios.post(...)
而不是在 addRunConfig 对象中定义所有内容?
不确定它是否有所作为,但值得一试。
,这里对定义函数、调用函数和异步函数的概念有些混淆。
首先:如果您正在调用一个异步函数并且不希望您的调用函数在该异步函数返回之前返回,您希望await
该调用。
在这种情况下,您的 recordResults
函数等待某些东西,因此是异步的。因此,您可能希望 onRunnerEnd
等待您对 recordResults
的调用。如果您不这样做,该函数将过早终止并且可能不会等待结果。
async onRunnerEnd(suite) {
console.log("CHECKPOINT RUNNER END")
await this.recordResults(caseIds[5],results[5],'renters api tests',5);
}
其次,如果同时使用 then
和 await
,await
表达式返回的值是 then
中函数返回的任何值。因此,您在 then
调用的函数内没有返回值的所有尝试都将永远不会返回空承诺之外的任何内容。没有理由将这些概念结合起来。
第三,将函数调用(而不是声明或引用)放入 then 子句中,将立即调用该函数。 IE。 .then(console.log('WHAAAT?'))
只是立即调用 console.log 并注册一个不存在的函数作为 then
的回调(因为 console.log
不返回函数引用)。
最后,传递未绑定的函数一般是行不通的。根据 testRun.then(console.log)
和 then
的实现,执行 console.log
之类的操作将不起作用。为了安全起见,请执行 testRun.then(console.log.bind(console)
或 testRun.then((x) => console.log(x))
。
因此,首先,在 onRunnerEnd
中添加 await,然后只使用 await 结果,而不要在 then
中使用任何 addRun
或 catch:
async addRun(suiteId,caseIds,name = '',projectId) {
console.log("CHECKPOINT ADD RUN")
let addRunConfig = {
method: 'post',url: `https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`,headers: {
'Content-Type': 'application/json',Authorization: token,Cookie: 'tr_session=041c4349-688f-440a-95a3-afc29d39320a'
},data: JSON.stringify({
suite_id: suiteId,include_all: false,case_ids: caseIds,name: name
})
};
// let x = axios.get('https://www.google.com/')
// console.log(x)
axios.defaults.timeout = 1000;
let response = await axios(addRunConfig);
console.log(response);
console.log(response.data.id);
return response.data.id;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。