【发布时间】:2021-08-12 17:44:01
【问题描述】:
我正在创建一个循环来使用具有内置承诺的函数来创建/更新用户:
for (const user of usersjson.users) {
let getuser = getUser(url, okapikey, user[fieldMap.externalSystemId],
'externalSystemId'); //Check if user exists on the server
await getuser
.then(async (data) => {
if (data.users.length != 0) { //If user exists in the array
update = updateUser(url, okapikey, createduser, data.users[0].id);//Create update function
promises.push(update); //Store function in array
i++;
} else {
create = createNewUser(url, okapikey, createduser);//Create create function
promises.push(create); //Store function in array
i++;
}
}).catch((err) => {
console.error(err);
});
if (promises.length == 50 || i == usersjson.users.length) {//Run functions in batches of 50
await Promise.allSettled(promises)
.then((responses)=> {
for (const response of responses) { //For each promise response
if (response.status == 'fulfilled') { //If fulfilled
if (response.value.status == 204) {
console.log(`${response.value.status}: User ${response.value.request.path.substring(7)} was updated.`);
} else {
if (response.value.status == 201 && response.value.headers.location) {
console.log(`${response.value.status}: User ${response.value.headers['location']} was created.`);
} else {
console.log(response.value.headers.location);
}
}
} else { //Handle rejections
console.log(`There was an error with the user:${response.value}`);
}
}
}).catch((err)=> {
console.log(err);
});
promises=[]; //Empty Promise array
}
}
async function updateUser(url, token, user, userid)
{
return new Promise((resolve, reject) => {
//Create headers for put request
const options = {
method: "put",
headers: {
'x-okapi-token': token,
'x-okapi-tenant':'tenant',
'Content-type':"application/json"
}
};
//Make API get call
user.id=userid; //Adding the required field ID to the JSON
axios.put(`${url}/users/${userid}`, JSON.stringify(user), options)
.then(response => {
if (response.status == 204) {
resolve(response);
} else {
reject(`Error Code: ${err.response.status}\nError Text: ${err.response.data.errors[0].message}\nError Status: ${err}`);
}
}).catch((err) => {
console.error(`Error Code: ${err.response.status}`);
if (typeof err.response.data == 'string') {
console.error(err.response.data);
reject(`Error Code: ${err.response.status}\nError Text: ${err.response.data.errors[0].message}\nError Status: ${err}`);
} else if (err.response.data.errors[0].message) {
console.error(`Error Text: ${err.response.data.errors[0].message}`);
reject(`Error Code: ${err.response.status}\nError Text: ${err.response.data.errors[0].message}\nError Status: ${err}`);
} else {
reject(`Error Code: ${err.response.status}\nError Text: ${err.response.data.errors[0].message}\nError Status: ${err}`);
}
console.log(err.response);
});
});
};
async function createNewUser (url, token, user) {
return new Promise((resolve, reject) => {
//Create headers for put request
const options = {
headers: {
'X-Okapi-token': token,
'Content-type':"application/json"
}
};
//Make API get call
axios.post(`${url}/users`, JSON.stringify(user), options)
.then(response => {
if (response.status == 201) {
resolve(response);
} else {
reject(`Error Code: ${err.response.status}: ${user.externalSystemId},\nError Text: ${err.response.data.errors[0].message},\nError Status: ${err}`)
}
}).catch((err) => {
console.error(`Error on ${user.externalSystemId}: ${err}`);
if (err.response.data && typeof err.response.data == 'string') {
console.error(err.response.data);
reject(`Error Code: ${err.response.status}: ${user.externalSystemId},\nError Text: ${err.response.data.errors[0].message},\nError Status: ${err}`)
} else if (err.response.data.errors[0].message) {
console.error(`Error Text: ${err.response.data.errors[0].message}`);
reject(`Error Code: ${err.response.status}: ${user.externalSystemId},\nError Text: ${err.response.data.errors[0].message},\nError Status: ${err}`)
} else {
reject(`Error Code: ${err.response.status}: ${user.externalSystemId},\nError Text: ${err.response.data.errors[0].message},\nError Status: ${err}`)
}
});
});
};
const getUsers = (url,user,password) =>
{
return new Promise((resolve, reject) => {
//Create headers for POST request
const options = {
method: 'post',
headers: {
'Authorization': 'Basic '+Buffer.from(`${user}:${password}`).toString('base64')
}
}
//Make API get call
axios.get(url, options)
.then(response => {
resolve(response.data);
}).catch((err) => {
console.error(err);
reject(err);
});
});
};
当每一个承诺都被履行时,代码和循环都可以正常工作,但一旦承诺被拒绝,循环就会中断。我收到错误消息,例如:
XXX 错误:错误:请求失败,状态码为 422 错误文本: 具有此用户名的用户已存在 节点:内部/进程/承诺:246 triggerUncaughtException(err, true /* fromPromise */); ^
[UnhandledPromiseRejection:此错误源于抛出 在没有 catch 块的异步函数内部,或通过拒绝 未使用 .catch() 处理的承诺。承诺被拒绝 原因“错误代码:422:XXX,错误文本:具有此用户名的用户 已存在,错误状态:错误:请求失败,状态码 422"。] {}
查看代码和错误,我相信这是来自“createNewUser”函数。 我不确定为什么代码会中断 - 我在所有函数中添加了 catch,处理了拒绝,并在代码主体中添加了 catch 语句,但循环仍然中断。
我需要的是让循环像往常一样继续,即使一个函数失败(我稍后会将日志从 console.log 更改为实际的日志文件)。
【问题讨论】:
-
顺便说一句,避免
updateUser/createNewUser/getUsers函数中的Promiseconstructor antipattern! -
你误用/误解了
await。let getUser = getUser(...); await getUser.then(data => ...)与let data = await getUser(...); ...相同,在这种情况下尽量不要将await与.then混合使用 -
@Bergi 既然您在这里提供了帮助并且我实现的代码是您建议的更改,我想也许您可以帮助解决由此引起的奇怪问题。在以前的版本中没有发生这种情况,只有在我将数组更改为您向我展示的函数时:stackoverflow.com/questions/67677866/…
标签: node.js loops promise catch-block