[英]Wait for async method in for loop in Cypress
編輯:為什么這不是重復的:因為Cypress ,只是讀取而不是將所有內容標記為重復。
編輯 2:另外,請參閱答案以更好地理解通常的 async for
循環問題與此問題之間的差異。
我正在編寫 cypress 測試,我想創建一個 cypress 命令,用用戶列表填充我的數據庫。 我希望創建循環在移動到下一個用戶之前等待創建每個用戶(因為我希望以特定順序完成)。
現在,我的循環如下所示:
Cypress.Commands.add("populateDb", (users) => {
var createdItems = []
for (const user of users) {
cy.createUser(user, 'passe').then(response => {
createdUsers.unshift(response.body.user)
})
}
return createdItems
})
當然,這個循環在移動到下一個用戶之前不會等待每個用戶被創建(我想要“順序處理”,而不是“並行然后等待所有承諾解決”)
我在這里閱讀了有關異步 for 循環的答案:
但我似乎找不到我想要的東西,主要是因為 cypress 不允許我將我的函數聲明為異步,如下所示:
Cypress.Commands.add("populateDb", async (users) => {
//Some code
})
如果我不將其聲明為async
我將無法使用await
。
是不是有一些get()
方法之王只是同步等待 Promise 解析?
使用wrap
和each
cypress 命令的組合,我能夠實現一個循環,該循環等待每次迭代,並且無需全局變量即可返回完整結果。
我使用wrap
命令的唯一原因是因為each
cypress 命令each
要求將它與之前的 cypress 命令鏈接起來。 each
命令將評估每次迭代並最終調用then
,您可以在其中返回完整的結果數組。 我正在使用它來上傳多個文件並返回密鑰列表,但您可以根據自己的需要修改它。
Cypress.Commands.add("uploadMultipleFiles", (files) => {
var uploadedS3Keys = []
cy.wrap(files).each((file, index, list) => {
cy.uploadFileToOrdersApi(file)
.then(s3Key => uploadedS3Keys.push(s3Key))
}).then(() => uploadedS3Keys)
})
事實證明,cypress 對等待異步方法解決的操作如此嚴格是有原因的:它總是按順序自動運行所有異步命令,因為它們被調用,而不是並行,所以這將在即使createUser
是 Async 的正確順序:
Cypress.Commands.add("populateDb", (users) => {
for (const user in users) {
cy.createUser(user).then(response => {
console.log(response)
})
}
})
如果您想獲取返回的值(在我的情況下,我需要用戶 ID 以便稍后刪除它們),您可以將它們存儲在文件根級別的var
,並添加一個返回該 var 的 cypress 命令。
var createdItems = []
Cypress.Commands.add("getCreatedItems", () => {
return createdItems
})
Cypress.Commands.add("populateDb", (users) => {
for (const user in users) {
cy.createUser(user).then(response => {
createdItems.unshift(response) // I unshift() because I need to delete them in FILO order later
})
}
})
然后在 cypress 測試文件中,您可以按照需要執行的順序調用它們:
cy.populateDb(users)
cy.getCreatedItems().then(response => {
//response is my createdItems Array, and cy.getCreatedItems() will run only when cy.populateDb() is resolved
})
你也可以這樣做:
Cypress.Commands.add("populateDb", (users) => {
for (const user in users) {
cy.createUser(user).then(response => {
createdItems.unshift(response) // I unshift() because I need to delete them in FILO order later
})
}
return createdItems;
})
cy.populateDb(users).then(response => {
// ... runs after populate ...
})
但另一個答案也是正確的。 每個cy.xxxxx
命令實際上都被添加到命令隊列中並一個接一個地運行。 如果在隊列執行期間調用了新的cy.xxxxx2
命令,它們將被添加到隊列的前面。
下面簡單舉例說明cypress命令隊列和同步代碼的執行順序:
const a = 1; // a == 1
cy.cmd1().then(() => {
cy.cmd2().then(() => {
a += 1; // a == 5
});
a += 1; // a == 3
cy.cmd3()
a += 1; // a == 4
});
cy.cmd4().then(() => {
a += 1; // a == 6
});
a += 1; // a == 2
// at this point cypress command queue starts running the queue that is cmd1, cmd4
// 1. cmd1 runs and adds cmd2 and cmd3 to front of command queue also adds +2 to a
// 2. cmd2 runs and adds +1 to a
// 3. cmd3 runs
// 4. cmd4 runs and adds +1 to a
// ... all done ...
所以從這個例子你可以看到,在你的情況下,你的循環將被串行執行,因為每個cy.createUser
被添加到 cypress 命令隊列中,然后按順序執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.