一个承诺可以解决两次吗?
Can one promise be resolved twice?
我有这样的功能:
async howLongToMyBirthdayDate(date) {
return await new Promise((resolve, reject) => {
let bday;
if (!(date instanceof Date)) {
if (Number.isInteger(date) && date > 0) {
bday = new Date(date);
} else {
setTimeout(() => reject(new Error('Wrong argument!')), 1000);
return;
}
} else {
bday = date;
}
const today = new Date();
today.setHours(0, 0, 0, 0);
bday.setFullYear(today.getFullYear());
bday.setHours(0, 0, 0, 0);
if (bday - today === 0) {
setTimeout(() => resolve(this.congratulateWithBirthday()), 1000);
}
setTimeout(
() =>
resolve(this.notifyWaitingTime(Math.ceil((bday - today) / 86400000))),
1000
);
});
}
承诺解决了两次。我看到函数 congratulateWithBirthday 和 notifyWaitingTime 的结果。正常吗?我认为 promise 只能被解决或拒绝一次——通过第一次调用 resolve 或 reject 回调。也许 setTimeout 改变了它的行为?谁能给我解释一下?
您的承诺无需解析两次即可获得您描述的行为。您直接调用了这两个函数,因此它们当然会被调用。第二次调用 resolve
是否执行任何操作无关。
这一行
resolve(this.notifyWaitingTime(Math.ceil((bday - today) / 86400000))),
不是说“解析然后运行这个函数”,而是说“调用这个函数,然后用它的return值调用解析”。
编写此代码的更合适的方式可能是这样的:
async howLongToMyBirthdayDate(date) {
const result = await new Promise((resolve, reject) => {
let bday;
if (!(date instanceof Date)) {
if (Number.isInteger(date) && date > 0) {
bday = new Date(date);
} else {
setTimeout(() => reject(new Error('Wrong argument!')), 1000);
return;
}
} else {
bday = date;
}
const today = new Date();
today.setHours(0, 0, 0, 0);
bday.setFullYear(today.getFullYear());
bday.setHours(0, 0, 0, 0);
// resolve with how long until bday
if (bday - today === 0) {
setTimeout(() => resolve(0), 1000);
}
// we just resolve with how long until bday
setTimeout(
() =>
resolve(Math.ceil((bday - today) / 86400000)),
1000
);
});
if (result === 0) { this.congratulateWithBirthday(); }
else if (result > 0) { this.notifyWaitingTime(result); }
}
不能 100% 确定这会解决你的问题,因为我看不到你调用的函数是做什么的,但我从你(ab)使用 resolve
的方式猜测你基本上想要根据现在是否是生日,在计算后调用两个函数之一。
简短回答,是的,根据您的代码,它将解析两次。这样做的原因是因为 congratulateWithBirthday
和 notifyWaitingTime
不以彼此为条件,因此它们将在相同的 运行.
上被调用
如果你想避免这种情况,你应该有类似的东西
if (bday - today === 0) {
setTimeout(() => resolve(this.congratulateWithBirthday()), 1000);
} else {
setTimeout(() => resolve(this.notifyWaitingTime(Math.ceil((bday - today) / 86400000))), 1000);
}
此外,作为旁注,请尝试在使用 async/await
或 Promise
之间做出决定。没有理由同时使用两者,这会使代码看起来很奇怪。
我有这样的功能:
async howLongToMyBirthdayDate(date) {
return await new Promise((resolve, reject) => {
let bday;
if (!(date instanceof Date)) {
if (Number.isInteger(date) && date > 0) {
bday = new Date(date);
} else {
setTimeout(() => reject(new Error('Wrong argument!')), 1000);
return;
}
} else {
bday = date;
}
const today = new Date();
today.setHours(0, 0, 0, 0);
bday.setFullYear(today.getFullYear());
bday.setHours(0, 0, 0, 0);
if (bday - today === 0) {
setTimeout(() => resolve(this.congratulateWithBirthday()), 1000);
}
setTimeout(
() =>
resolve(this.notifyWaitingTime(Math.ceil((bday - today) / 86400000))),
1000
);
});
}
承诺解决了两次。我看到函数 congratulateWithBirthday 和 notifyWaitingTime 的结果。正常吗?我认为 promise 只能被解决或拒绝一次——通过第一次调用 resolve 或 reject 回调。也许 setTimeout 改变了它的行为?谁能给我解释一下?
您的承诺无需解析两次即可获得您描述的行为。您直接调用了这两个函数,因此它们当然会被调用。第二次调用 resolve
是否执行任何操作无关。
这一行
resolve(this.notifyWaitingTime(Math.ceil((bday - today) / 86400000))),
不是说“解析然后运行这个函数”,而是说“调用这个函数,然后用它的return值调用解析”。
编写此代码的更合适的方式可能是这样的:
async howLongToMyBirthdayDate(date) {
const result = await new Promise((resolve, reject) => {
let bday;
if (!(date instanceof Date)) {
if (Number.isInteger(date) && date > 0) {
bday = new Date(date);
} else {
setTimeout(() => reject(new Error('Wrong argument!')), 1000);
return;
}
} else {
bday = date;
}
const today = new Date();
today.setHours(0, 0, 0, 0);
bday.setFullYear(today.getFullYear());
bday.setHours(0, 0, 0, 0);
// resolve with how long until bday
if (bday - today === 0) {
setTimeout(() => resolve(0), 1000);
}
// we just resolve with how long until bday
setTimeout(
() =>
resolve(Math.ceil((bday - today) / 86400000)),
1000
);
});
if (result === 0) { this.congratulateWithBirthday(); }
else if (result > 0) { this.notifyWaitingTime(result); }
}
不能 100% 确定这会解决你的问题,因为我看不到你调用的函数是做什么的,但我从你(ab)使用 resolve
的方式猜测你基本上想要根据现在是否是生日,在计算后调用两个函数之一。
简短回答,是的,根据您的代码,它将解析两次。这样做的原因是因为 congratulateWithBirthday
和 notifyWaitingTime
不以彼此为条件,因此它们将在相同的 运行.
如果你想避免这种情况,你应该有类似的东西
if (bday - today === 0) {
setTimeout(() => resolve(this.congratulateWithBirthday()), 1000);
} else {
setTimeout(() => resolve(this.notifyWaitingTime(Math.ceil((bday - today) / 86400000))), 1000);
}
此外,作为旁注,请尝试在使用 async/await
或 Promise
之间做出决定。没有理由同时使用两者,这会使代码看起来很奇怪。