网站搜索

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)。