javascript - 如何在 TypeScript 函数中让返回等待一个超时
我正在尝试创建一个返回 Promise 的方法,但我需要在超时后才能返回该 Promise 的数据。问题是,方法在超时结束之前就返回了 Promise,所以数据是不正确的。你知道有什么方法可以让返回等待超时完成后再解析吗?谢谢 :)
`
export default async function scrapper(city: string): Promise<Coords> {
let latitude = "";
let longitude = "";
let driver = openDriver();
setTimeout(async () => {
await driver.findLatitude(city).then((value) => {
latitude = value;
}).then(async () => {
await driver.findLongitude(city).then((value) => {
longitude = value;
});
}).then(async () => {
await driver.quit();
});
}, 1000);
return new Promise(async (resolve) => { resolve({ lat: latitude, long: longitude }) })
}
`
01234567890123456789
答案#1
通常避免 new Promise。这样做的唯一目的,是将回调风格的代码转换为 Promise。在同步中直接调用 resolve(...) 从来没有意义。为此,可以使用 Promise.resolve(...)。
异步函数 总是 自动返回一个 Promise。所以不需要自己去创建一个。
现在,new Promise 的少数几个用例之一实际上是 setTimeout。一个常见的技巧是这样的:
const wait = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
这给了你一个简单的函数,它会等待一段时间,你可以像 await wait(1000) 一样使用 await。
在下一步中,重要的是要意识到这些这一点:
await driver.findLatitude(city).then((value) => {
latitude = value;
})
与此完全相同:
latitude = await driver.findLatitude(city);
这意味着你可以像这样重写你的代码:
const wait = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
export default async function scrapper(city: string): Promise<Coords> {
let latitude = "";
let longitude = "";
let driver = openDriver();
await wait(1000);
latitude = await driver.findLatitude(city)
longitude = await driver.findLongitude(city);
await driver.quit();
return { lat: latitude, long: longitude };
}
接下来的步骤是移除 let,并将它们替换为 const。
答案#2
首先我会建议几件事。
对于你所问的,你需要将所有内容封装在 Promise 中,并在 setTimeout 中解决它。
我建议你使用 Promise.all() 来在进行多个 HTTP 请求时节省大量时间。
(仅在你所进行的调用彼此独立时使用)
它应该看起来像这样:
promiseExample() {
return new Promise((resolve, reject) => {
const promiseArray = [];
const driver = openDriver();
promiseArray.push(driver.findLatitude(city))
promiseArray.push(driver.findLongitude(city))
promiseArray.push(driver.quit()) // if this action not depend on the rest if it does put it inside the then
Promise.all(promiseArray)
.then((result) => {
setTimeout(() => {
resolve({ lat: result[0], long: result[1] });
}, 1000) // use here what ever time you want
})
})
}
或者以 async 的方式:
export default async function scrapper(city: string) {
let driver = openDriver();
const promiseArray = []
promiseArray.push(driver.findLatitude(city));
promiseArray.push(driver.findLongitude(city));
// if driver.quit() depened on other then if not the add it like the others
const result = await Promise.all(promiseArray);
await driver.quit();
setTimeout(() => {
return { lat: result[0], long: result[1] }
}, 1000);
}
使用 promise all 会加快 API 请求速度,让你等待时间大大减少。因为你是先发出所有请求,然后等待所有响应,而不是发出请求等待响应再发下一个请求等。
此外,如果需要,你应该实现 reject(用于 promise)或使用 try catch(用于 async)。
