簡體   English   中英

遞歸等待 promise 解決后什么都不做

[英]Recursive awaited promise does nothing after resolving

我正在向 Twitter API 發出一些請求,為了檢索推文,我需要執行一些遞歸方法調用,因為每個請求最多只能返回 100 條推文。

所以這個過程非常簡單。

  1. 致電 function 並等待
  2. 執行 http 請求,等待
  3. 如果響應的元數據包含next_token ,則緩存結果並使用下一個令牌執行另一個 http 請求。
  4. 重復直到next_token未定義,此時使用所有推文列表解析 promise。

然而這並沒有按預期工作,遞歸 http 工作,但是當遞歸 function 的 else 塊滿足並且 promise 得到解決時,什么也沒有發生。 執行不會 go 回到第一個 function。 一切似乎都在旋轉,什么也不做。 我在每一行都添加了斷點,但沒有任何東西會觸發斷點。

我在哪里錯了?

public async getTweetList(ticker: string): Promise<string[]>{
        let tweets: string[] = [];

        tweets = await this.getAllTweetsRecursively(ticker, null, tweets);
        return tweets;
    }

    public async getAllTweetsRecursively(ticker: string, nextToken: string, tweetList: string[]): Promise<string[]>{
        return new Promise(async (resolve, reject) => {
            let query = `?query=(${ticker})`
            query += this.extraQuery;

            if(nextToken){
                query += this.nextTokenQuery + nextToken
            }

            let res = await axios.default.get(this.url + query, {
                headers: this.headers
            })

            let newNextToken = res.data.meta.next_token;
            if(res.data.data.length > 0 && newNextToken){
                res.data.data.forEach(tweet => {
                    tweetList.push(tweet.text);
                })
                this.getAllTweetsRecursively(ticker, newNextToken, tweetList);
            }
            else {
                resolve(cleanedTweets)
            }
        })
    }

替代實施 - 同樣的問題

public async getTweetList(ticker: string): Promise<string[]>{
        return new Promise(async (resolve) => {
            let tweets: string[] = [];

            tweets = await this.getAllTweetsRecursively(ticker, null, tweets);
            resolve(tweets);
        })

    }

    public async getAllTweetsRecursively(ticker: string, nextToken: string, tweetList: string[]): Promise<string[]>{
        return new Promise(async (resolve, reject) => {
            let query = `?query=(${ticker})`
            query += this.extraQuery;

            if(nextToken){
                query += this.nextTokenQuery + nextToken
            }

            let res = await axios.default.get(this.url + query, {
                headers: this.headers
            })

            let newNextToken = res.data.meta.next_token;
            if(res.data.data.length > 0 && newNextToken){
                res.data.data.forEach(tweet => {
                    tweetList.push(tweet.text);
                })
                await this.getAllTweetsRecursively(ticker, newNextToken, tweetList);
            }
            else {
                let cleanedTweets: string[] = [];
                tweetList.forEach(tweet => {
                    if(tweet.startsWith("RT")){
                        return;
                    }
                    if(!tweet.toLowerCase().includes("$" + ticker)){
                        return;
                    }
                    cleanedTweets.push(tweet);
                });
                resolve(cleanedTweets)
            }
        })
    }

問題是內部 promise 在遞歸調用自身的情況下沒有解決。

添加resolve(await this.getAllTweetsRecursively(ticker, newNextToken, tweetList)); 解決了這個問題。

public async getTweetList(ticker: string): Promise<string[]> {
  let tweets: string[] = [];
  return await this.getAllTweetsRecursively(ticker, null, tweets);
}

public async getAllTweetsRecursively(ticker: string, nextToken: string, tweetList: string[]): Promise<string[]>{
  return new Promise(async (resolve, reject) => {
    let query = `?query=(${ticker})`
    query += this.extraQuery;

    if(nextToken){
      query += this.nextTokenQuery + nextToken
    }

    let res = await axios.default.get(this.url + query, {
      headers: this.headers
    })

    let newNextToken = res.data.meta.next_token;
    if(res.data.data.length > 0 && newNextToken){
      res.data.data.forEach(tweet => {
        tweetList.push(tweet.text);
      })
      resolve(await this.getAllTweetsRecursively(ticker, newNextToken, tweetList));
    }
    else {
      res.data.data.forEach(tweet => {
        tweetList.push(tweet.text);
      })
      let cleanedTweets: string[] = [];
      tweetList.forEach(tweet => {
        if(tweet.startsWith("RT")){
          return;
        }
        if(!tweet.toLowerCase().includes("$" + ticker)){
          return;
        }
        cleanedTweets.push(tweet);
      });
      resolve(cleanedTweets)
    }
  })
}

請記住async function() {}已經定義了一個返回 Promise的函數,因為這就是async關鍵字為您所做的。 它通過將 function 主體包裝在 Promise 中來使您的主體異步,而無需您自己編寫 promise 代碼。 然后為方便起見, await關鍵字相當於Promise.then(),無需自己編寫提取代碼。

因此,以下兩個功能是相同的:

function() {
  return new Promise(resolve, reject => {
    resolve(4);
  });
}

async function() {
  return 4;
}

兩者都返回 Promise,兩者都可以在另一個async function 中await ,並且兩者都可以用 .then .then()鏈接,因為它們實際上是同一件事。 所以對於你的代碼,如果你想使用async / await你不應該也構建 Promises:

public async getTweetList(ticker: string): Promise<string[]> {
  return await this.getAllTweetsRecursively(ticker, null, []);
}

public async getAllTweetsRecursively(ticker: string, nextToken: string, tweetList: string[]): Promise<string[]>{
    let query = `?query=(${ticker})${this.extraQuery}`;

    if(nextToken){
      query = `${query}${this.nextTokenQuery}${nextToken}`;
    }

    let res = await axios.default.get(this.url + query, {
      headers: this.headers
    })

    let newNextToken = res.data.meta.next_token;
    if(res.data.data.length > 0 && newNextToken){
      res.data.data.forEach(tweet => tweetList.push(tweet.text))
      return await this.getAllTweetsRecursively(ticker, newNextToken, tweetList));
    }

    // no need for "else": the "if" already returns.

    res.data.data.forEach(tweet => tweetList.push(tweet.text))
    let cleanedTweets: string[] = [];
    tweetList.forEach(tweet => {
      if(tweet.startsWith("RT")) return;
      if(!tweet.toLowerCase().includes("$" + ticker)) return;
      cleanedTweets.push(tweet);
    });

    return cleanedTweets
  })
}

您的代碼包含async getAllTweetsRecursively(...) { return new Promise(async (resolve, reject) => {... }))現在將返回三個嵌套的承諾,因為這些async關鍵字使得:

getAllTweetsRecursively(...) {
  return new Promise(resolve, reject => {
    return new Promise(async (resolve, reject) => {
      ...
    }))
  });
}

由於該async進一步展開為:

getAllTweetsRecursively(...) {
  return new Promise(resolve, reject => {
    return new Promise((resolve, reject) => {
      return new Promise(resolve, reject => {
        resolve(...)
      })
    }))
  });
}

這種方式是瘋狂的=)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM