【问题标题】:NodeJS async/await + recursion on express requestNodeJS async/await + 快速请求递归
【发布时间】:2018-02-09 18:25:24
【问题描述】:

我有一个名为 GetAllData() 的函数,它调用 GetPurchaseData,它递归地调用自身,直到它加载所有数据。在

async function GetAllData(){
    console.log("starting loading purchase data");
        await GetPurchaseData();
        console.log("purchase data loaded")        
}

async function GetPurchaseData(){
         return new Promise(async function (resolve,reject){
            var Headers = {
                ....
            }
            await request({url: xxx, headers: Headers },async function(error, response, body) {
                    var tmp = JSON.parse(body)      
                    _.forEach(tmp.Purchases, p => purchaseData.push(p));                          

                    if (response.headers.pagination){
                        return await GetPurchasePaginatedData()
                    }
                    else{
                        console.log("done loading....")
                        return resolve("done")
                    }
            });
        })
}

Node JS 打印以下输出:

starting loading purchase data 
done loading....

但它永远不会返回到 GetAllData 来打印

已加载购买数据

它几乎看起来像是卡在了函数中,但我认为“return resolve(“done”)”这一行并没有回到最初的调用,以实际将 Promise 标记为完成。

【问题讨论】:

  • 需要注意的是,您不需要从async function 显式返回Promiseasync 规定您的函数无论如何都将返回Promise
  • 另外,request 接受Promise 还是回调?上次我使用它时,它希望以标准 node.js 方式进行回调。如果是这种情况,您需要包装 request 或找到在 Promises 中工作的库。
  • 我正在通过 return new Promise( ... request() ... ) 包装请求,我不是吗?
  • 您使用的是哪个确切请求库?如果它是常规的,它只适用于你没有正确包装的回调。由于您正在使用Promisesasync/await,我实际上建议使用request 提供的包装库之一。你可以选择request's GitHub中的任何一个。
  • @zero298 哈哈!!有趣的!我正在使用常规请求库。你能发布一个正确包装方式的例子吗?

标签: javascript node.js express asynchronous recursion


【解决方案1】:

避免使用async/await Promise constructor antipattern(另请参阅here),并避免将async 函数作为常规回调传递——您需要use the Promise constructor to promisify an existing callback API

async function GetPurchaseData() {
    var headers = {…};
    var promise = new Promise((resolve,reject) => { // not async!
        request({url: xxx, headers}, (error, response, body) => { // not async!
            if (error) reject(error);
            else resolve({response, body});
        });
    }); // that's it!

    var {response, body} = await promise;
    for (var p of JSON.parse(body).Purchases)
        purchaseData.push(p));                          

    if (response.headers.pagination) {
        return GetPurchasePaginatedData()
    } else {
        console.log("done loading....")
        return "done";
    }
}

【讨论】:

    【解决方案2】:

    我对 async/await 没有太多经验,但根据我的阅读,代码不应该是这样的吗?

    async function GetAllData(){
        console.log("starting loading purchase data");
            await GetPurchaseData();
            console.log("purchase data loaded")        
    }
    
    async function GetPurchaseData(){
            let body = await request({url: xxx, headers: Headers })
    
            var tmp = JSON.parse(body)      
            _.forEach(tmp.Purchases, p => purchaseData.push(p));                          
    
            if (response.headers.pagination){
                return await GetPurchasePaginatedData()
            }
            else{
                console.log("done loading....")
                return "done"
            }
    }
    

    【讨论】:

    • 那是我最初的方法,除了 let body 我正在做 let response 然后我将响应拆分为 response.headersresponse.body,但它没有工作。 “没有工作”我的意思是它实际上并没有等待响应回来
    猜你喜欢
    • 2018-04-02
    • 2012-11-28
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多