首页 > 解决方案 > 等到所有 http GET 请求完成后再登录到 JS 中的控制台

问题描述

Javascript/Node 菜鸟在这里。在理解 JS 的整个异步方面时遇到了一些麻烦。我正在构建一个小型应用程序,其目的是调用外部 API,然后存储结果以用于日志记录。

无论如何,我有一个看起来像这样的 GET 请求

request(callsOptions)
.then(function (res) {
    //Request success... do some logic with the response object
    var content = JSON.stringify(res)
    //save result to a file with the name as m-d-yyyy.json
    fs.writeFile(`callLogs/${month}-${day}-${year}.json`, content, 'utf8', function (err) {
        if (err) {
            return console.log(err);
        }
    })        
    //get session_ids and call destinations and store in the 2 diff arrays
    var calls = res.calls
    for(let x = 0; x < calls.length; x++){
        session_ids[x] = calls[x].session_id
        dests[x] = calls[x].dest
    }
    //make an individual req for each call in the array
    for(let x = 0; x < calls.length; x++){
        getCallLog(session_ids[x], dests[x])
    }
}).catch(function (err) {
    //Request failure...
    console.log('Whoops... something went wrong with the calls request!')
})

然后调用 getCallLog 方法,该方法获取从前一个请求中提取的信息并进行更多调用

function getCallLog(id, dest){
request(constructURL(id))
    .then(function (res) {
        //Request success... do some logic with the response object
        console.log('Request success!')
        var content = JSON.stringify(res)
        fs.writeFile(`${dest}/${id}.json`, content, 'utf8', function (err) {
            if (err) {
                return console.log(err);
            }
        })
        //return res
    }).catch(function (err) {
        //Request failure...
        console.log('Whoops... something went wrong with the call request!')
    })

}

所以,我想等到所有 GET 请求完成之后再做一些逻辑。目前,该逻辑将简单地类似于

    console.log('DONE')

问题是由于 JS 的异步方面,我尝试过的所有操作都会在完成之前显示 DONE。所以,我只是等待一段时间以确保所有请求都已完成。

我尝试过的事情:

编辑:像这样?

    const { promisify } = require("util")

...

request(callsOptions)
    .then(function (res) {
        //Request success... do some logic with the response object
        var content = JSON.stringify(res)
        //save result to a file with the name as m-d-yyyy.json under the callLogs folder
        fs.writeFile(`callLogs/${month}-${day}-${year}.json`, content, 'utf8', function (err) {
            if (err) {
                return console.log(err);
            }
        })
        //get session_ids and call destinations and store in the 2 diff arrays
        var calls = res.calls
        for (let x = 0; x < calls.length; x++) {
            session_ids[x] = calls[x].session_id
            dests[x] = calls[x].dest
        }
        //make an individual req for each call in the array
        const promises = [];
        for (let x = 0; x < calls.length; x++) {
            promises.push(getCallLog(session_ids[x], dests[x]))
        }
        return Promise.all(promises)
    }).then(function(){
        console.log("All done!")
    }).catch(function (err) {
        //Request failure...
        fs.writeFile(`errorlog/${month}-${day}-${year}.json`, content, 'utf8', function (err) {
            if (err) {
                return console.log(err);
            }
        })
    })

function getCallLog(id, dest){
request(constructURL(id))
    .then(function (res) {
        //Request success... do some logic with the response object 
        console.log('Request success!')
        var content = JSON.stringify(res)
        return promisify(fs.writeFile)(`${dest}/${id}.json`, content, 'utf8');
    }).catch(function (err) {
        //Request failure...
        fs.writeFile(`errorlog/${month}-${day}-${year}-${id}.json`, err, 'utf8', function (err) {
            if (err) {
                return console.log(err);
            }
        })
    })
    }

标签: javascriptnode.jsasynchronousnode-request

解决方案


只需从内部函数返回一个承诺并承诺文件写入:

const { promisify } = require("util");

function getCallLog(id, dest){
  return request(constructURL(id)) // <-- return the promise
   .then(function (res) {
      //Request success... do some logic with the response object
      console.log('Request success!')
      var content = JSON.stringify(res)
      return promisify(fs.writeFile)(`${dest}/${id}.json`, content, 'utf8');
  }).catch(function (err) { // also catches writing errors
    console.log('Whoops... something went wrong with the call request!')
  });
}

现在您可以在.your 循环中收集所有承诺:

const promises = [];
for(let x = 0; x < calls.length; x++){
    promises.push(getCallLog(session_ids[x], dests[x]));
}

然后将这些承诺返回到链中:

return Promise.all(promises);

因此,现在您可以将 a 添加.then(...)到随后将执行的链中:

.then(() => console.log("All done!"));

推荐阅读