![](/img/trans.png)
[英]How to wait for 3 Facebook Async functions to complete before pushing to array?
[英]Wait for promises to complete before pushing error array of objects to CSV
我正在嘗試從 Okta 導入和刪除大量用戶,同時保持在速率限制內,並將任何錯誤記錄到 excel。 下面的代碼似乎可以工作,但只是我在控制台日志上看到的 5 個錯誤中的最后一個沒有出現在輸出的 CSV 中。
我嘗試了一系列替代方法,包括將 csvWriter 調用放入 a.then 而不是 the.finally。 問題是它沒有等待最后一個錯誤被推送到數組。
"use strict"; const okta = require("@okta/okta-sdk-nodejs"); const csv = require("csv-parser"); const fs = require("fs"); const createCsvWriter = require("csv-writer").createObjectCsvWriter; let timeRun = new Date().toISOString().replace(/T/, " ") // replace T with a space.replace(/\..+/, "") // delete the dot and everything after.replace(/:/g, "."); // replace T with a space const csvWriter = createCsvWriter({ path: "errorLog-" + timeRun + ".csv", header: [ { id: "error", title: "Error" }, { id: "row", title: "Row" }, ], }); let record = []; let currentError = {} // Enter tenant info and API key here const client = new okta.Client({ orgUrl: "https://xxxxxxxx.oktapreview.com", token: "xxxxxxxxxxxxxxxxxxxxxxx", }); let usersToDelete = []; let currentUserID; var getUsersToDelete = new Promise((resolve, reject) => { fs.createReadStream("testImport.csv").pipe(csv()).on("data", (row) => { usersToDelete.push(row); }).on("end", (row) => { resolve(); }); }); getUsersToDelete.then(async () => { let iCount = 1; while (usersToDelete.length > 0) { var deleteUserTimeout = new Promise((resolve, reject) => { setTimeout(async function () { currentUserID = usersToDelete.pop(); client.getUser(currentUserID.email).then(async (user) => { return user.deactivate().then(() => console.log("User has been deactivated")).then(() => user.delete()).then(() => console.log("User has been deleted")); }).catch(async function (error, row) { currentError = { error: error.message, row: "row" }; console.error(currentError); return error; }).finally(() => { record.push(currentError); reject() }); resolve(); }, 2000); }); await deleteUserTimeout; console.log("Timeout" + currentUserID, "Iteration: " + iCount); iCount++ } }).finally(async () => { await csvWriter.writeRecords(record); });
在您的deleteUserTimeout
promise 中有一場比賽。 它在client.getUser
之后立即解決而不等待結果。
var deleteUserTimeout = new Promise((resolve, reject) => {
setTimeout(async function () {
currentUserID = usersToDelete.pop();
client.getUser(currentUserID.email) // forgot to await this
//... snip
resolve(); // resolves immediately
}, 2000);
});
await deleteUserTimeout; // this won't wait for the delete
為了清楚起見,我會對其進行重構(未經測試):
async function deleteUser(email) {
let user = await client.getUser(email);
await user.deactivate();
await user.delete();
}
function sleep(timeoutMs) {
return new Promise(_ => setTimeout(_, timeoutMs));
}
async function deleteUsers(usersToDelete) {
const errors = [];
for (let row = 0; row < usersToDelete.length; row++) {
let currentUserID = usersToDelete[row];
await sleep(2000);
await deleteUser(currentUserID.email)
.catch(error => {
errors.push({error: error.message, row});
});
}
return errors;
}
您的deleteUserTimeout
promise 沒有等待用戶刪除操作完成,並且腳本在為最后一個要刪除的用戶啟動setTimeout
回調后幾乎立即完成。 CSV 將寫入該時間累積的所有錯誤record
,而不是等待某些操作完成,包括遇到錯誤的 5 次迭代。
基本思想與@teppic 相同,但您可能希望在發現的每個錯誤時寫出,而不是將它們延遲到最后,以減少在腳本因任何原因崩潰時丟失錯誤信息的可能性(例如機器斷電)。
const sleep = time => new Promise(resolve => setTimeout(resolve, time))
const deleteUser = async email => {
const user = await client.getUser(email)
await user.deactivate()
await user.delete()
}
const deleteUsers = async users => {
for (const user of users) {
try {
await deleteUser(user.email)
console.log(`Deleted ${user.email}`)
await sleep(2000)
} catch (e) {
console.error(e.message)
await csvWriter.writeRecords([{error: e.message, row: 'row'}])
}
}
}
getUsersToDelete.then(() => deleteUsers(usersToDelete))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.