Typescript 尽管在异步函数中返回了值,Promise始终解析为null
我的Typescript 尽管在异步函数中返回了值,Promise始终解析为null,typescript,promise,Typescript,Promise,我的async函数有问题 在内部promisethen回调中,值设置正确,但在返回此变量并解析promise之后,调用方始终会得到一个空值 注意:这是针对discord机器人的:我尝试使用用户ID获取用户的显示名称 以下是async函数: export async function getUserInfo(userNameLooking: string, guild: Guild): Promise<UserSettings | null> { console.log(&quo
async
函数有问题
在内部promisethen
回调中,值设置正确,但在返回此变量并解析promise之后,调用方始终会得到一个空值
注意:这是针对discord机器人的:我尝试使用用户ID获取用户的显示名称
以下是async
函数:
export async function getUserInfo(userNameLooking: string, guild: Guild): Promise<UserSettings | null> {
console.log("Looking for user", userNameLooking);
userList.forEach(user => {
console.log("Analyzing user ID", user);
let thanos = guild.client.users.fetch(user);
thanos.then(function (result1) {
console.log("... This ID user name is", result1.username);
if (result1.username.toLowerCase() == userNameLooking.toLowerCase()) {
console.log("... Match !");
console.log(cacheUser[user] );
return cacheUser[user] ;
}
else {
console.log("... Not match ...");
}
}, function (){console.log("ERROR : Can't find name of ID", user)});
})
return null;
}
问题出在哪里?您的函数
getUserInfo
只有一个return
语句,它返回null
,因此它无法返回其他数据,以供承诺解决
问题是您的数据在forEach
回调函数中返回。但这个返回值将被遗忘。在forEach
回调中返回数据是无用的。它没有任何用途
您必须返回所有promise对象,您应该使用.map
,而不是.forEach
。然后使用Promise.all
等待所有这些承诺得到解决。然后使用.find
在未定义的值中查找第一个解析值。这是您希望用getUserInfo
承诺解析的值:因此返回该值
以下是它的工作原理:
export async function getUserInfo(userNameLooking: string, guild: Guild): Promise<UserSettings | null> {
let results = await Promise.all(userList.map(user => {
// ^^^^^^^^^^^ ^^^
let thanos = guild.client.users.fetch(user);
return thanos.then(function (result1) {
// ^^^^^^
if (result1.username.toLowerCase() == userNameLooking.toLowerCase()) {
return cacheUser[user];
}
});
});
// Find the first non-undefined result,
// ... assuming that `catchUser[user]` is a truthy value.
return results.find(Boolean);
}
Trincot的回答将针对所有用户运行查询,但即使在找到第一个结果后,它也会等待所有查询完成,然后再解析结果。这就是使用允诺的效果。所有这些都是他在回答中使用允诺的方式 我们真正想要的是一个类似于
Array.prototype.find的函数,但它接受一系列承诺。它应该在每一个上运行测试
功能,但是只要第一个值
通过测试,就可以解决问题。如果没有通过测试的承诺值,请解决undefined
-
异步函数查找(承诺、测试){
返回新承诺((解决、拒绝)=>{
for(承诺的常数)
p、 然后(值=>测试(值)和解析(值),拒绝)
Promise.all(promises).then(=>resolve(未定义))
})
}
将find
作为一个通用函数编写是很有用的,因为它允许getUserInfo
只关注它的特殊关注点。它还使我们能够重用查找程序中需要的其他位置,而无需编写复杂的代码-
函数getUserInfo(查询,公会){
返回查找
(userList.map(用户=>guild.client.users.fetch(用户))
,结果=>
result.username.toLowerCase()==query.toLowerCase()
)
。然后(user=>user&&cacheUser[user])
}
让我们使用下面的演示程序来看看find
-
异步函数查找(承诺、测试){
返回新承诺((解决、拒绝)=>{
for(承诺的常数)
p、 然后(值=>测试(值)和解析(值),拒绝)
Promise.all(promises).then(=>resolve(未定义))
})
}
const sleep=ms=>
新承诺(r=>setTimeout(r,ms))
异步函数获取(查询){
等待睡眠(Math.random()*3000)
返回查询
}
常量查询=
[“爱丽丝”、“鲍勃”、“卡拉”、“迪娜”]
查找(querys.map(fetch),result=>result.length>4)
.然后(console.log,console.error)/“卡拉”或“爱丽丝”
查找(querys.map(fetch),result=>result.length>5)
.then(console.log,console.error)//undefined
您的函数执行一个forEach
,然后执行返回null代码>。你还指望什么?这是它拥有的单个return
语句。但是在foreach中有一个return。。。否?是的,但这是回调函数的(无用)返回值,而不是外部函数的返回值。我理解,我将学习.map函数!谢谢!这个答案解释得很好,但在找到第一个匹配项时不会出现短路。请参阅我的答案,了解另一种方法:染料,@ThankYou,我也想到了捷径——这取决于第三方API,这可能会带来一些时间收益。我在我的答案中添加了一个替代的捷径解决方案,它不需要新承诺
。对承诺进行了很好的调整。任何
,但请注意,此解决方案都会吞下获取
过程中可能出现的其他自然错误。
export async function getUserInfo(userNameLooking: string, guild: Guild): Promise<UserSettings | null> {
let results = await Promise.all(userList.map(user => {
// ^^^^^^^^^^^ ^^^
let thanos = guild.client.users.fetch(user);
return thanos.then(function (result1) {
// ^^^^^^
if (result1.username.toLowerCase() == userNameLooking.toLowerCase()) {
return cacheUser[user];
}
});
});
// Find the first non-undefined result,
// ... assuming that `catchUser[user]` is a truthy value.
return results.find(Boolean);
}
// In this version the function does not really need to be declared `async`:
export function getUserInfo(userNameLooking: string, guild: Guild): Promise<UserSettings | null> {
return Promise.any(userList.map(user => {
// ^^^
let thanos = guild.client.users.fetch(user);
return thanos.then(function (result1) {
if (result1.username.toLowerCase() == userNameLooking.toLowerCase()) {
return cacheUser[user]; // <-- will resolve the `.any` promise
}
// Throwing will avoid resolving the `.any` promise
// ... unless this is the last one, and there was no match found
throw new Error("no match");
});
}).catch(() => null); // resolve to null when nothing matches
}