对许多用户来说,在Botkit上循环启动PrivateConversion方法



我正试图在一个单独的js文件中向所有用户发送更新,因此为了正确地执行此操作,我需要创建一个新的机器人控制器。我当前正在尝试调用控制器内部的通知函数。在rtm_open函数上。然后,我尝试迭代我的控制器存储的用户,并在他们的DM中向每个用户发送一条消息。这是我用于此方法的代码。

controller.on('rtm_open',function(bot) {
console.log('** The RTM api just connected!');
controller.storage.users.all(function(err, users) {
if (err) {
throw new Error(err);
console.log('Error hit in user storage')
})
updateInstallers(bot, users)
}

function updateInstallers(bot, users) {
console.log('Hello World', users)
var msg = 'Welcome to...., here is a list of our new features that you can try out with a reinstallation...'
for (var u in users) {
var installer = users[u].id
console.log('checking installer', installer)
bot.startPrivateConversation({user: installer}, function(err, convo) {     
console.log('Why is installer the SAME?', installer)
if (err) {
console.log(err)
} else {
console.log('Bot should say something', installer)
convo.say(msg)
}
})
}
}

在尝试以不同的方式开始循环之后,对于2个或更多用户的数组,最终结果总是这样。数组中的最后一个/最后一个用户对象始终是正确执行bot.startPrivateConversion函数的唯一用户。

checking installer U0T1AL5CN
checking installer UCSPVKE0H
Why is installer the SAME? UCSPVKE0H
Bot should say something UCSPVKE0H
Why is installer the SAME? UCSPVKE0H
user_not_found
Why is installer the SAME? UCSPVKE0H
Bot should say something UCSPVKE0H
Why is installer the SAME? UCSPVKE0H
user_not_found

你知道如何解决这个问题吗?我的猜测是,这是调用堆栈的异步问题,但我也担心这种类型的循环可能无法与此botkit函数一起使用。如果有一些代码,任何人都可以将其重构为更好的代码,那将是非常棒的。事先非常感谢。

您应该尝试以下操作:

for (let u in users) {
const installer = users[u].id

或者避免循环并使用forEach:

users.forEach(
(user)=>{
var installer = user.id;
//...rest of the code
}
)

但最好的方法可能是将用户数组映射到承诺:

//start conversation as promise
const startPrivateConversationPromise = (installer) =>
new Promise((resolve, reject) =>
bot.startPrivateConversation(
{ user: installer },
(err, convo) => (err ? reject(err) : resolve(convo)),
),
);
//special value for rejected promise
const Fail = function(reason) {
this.reason = reason;
};
const isFail = (o) => o && o.constructor === Fail;
const isNotFail = (o) => !o.isFail(o);
Promise.all(
users.map(
(user) =>
startPrivateConversationPromise(user.id).catch(
(e) => new Fail(e)//still resolve even if it rejects
), 
),
).then((results) => {
const convos = results.filter(isNotFail); //resolved instances
const failed = reslts.filter(isFail); //rejected instances
convos.forEach((convo) => convo.say(message));
});

最新更新