【问题标题】:Using async/await recursively with node request package在节点请求包中递归使用 async/await
【发布时间】:2018-04-02 03:07:18
【问题描述】:

我正在使用 response 节点库发出一个 http 请求,我正在尝试递归调用它(如果用户在某一天提交,请检查前一天。如果没有,请计算所有天数获得连胜)。

问题在于这条线

const githubResponse = await request(options);

吐出错误

Unexpected token o in JSON at position 1

await request(options) 似乎没有返回我期望的 JSON GitHub API 响应,而是 githubResponse 似乎是我无法使用的对象。我猜我使用 async/await 不正确,但我不知道如何解决它。

async function checkUserCommitForDate(user, date) {
    const options = {
        url: `https://api.github.com/search/commits?q=author:${user}+author-date:${date}`,
        headers: {
            'User-Agent': 'request',
            'Accept': 'application/vnd.github.cloak-preview'
        }
    };
    const githubResponse = await request(options)

    // I get an error on the next line

    if (JSON.parse(githubResponse).total_count > 0) {
        const previousDaysDate = moment(date).subtract(1, 'day').format('YYYY-MM-DD');
        let streakCounter = await checkUserCommitForDate(user, previousDaysDate);
        streakCounter++;
        console.log('streakCounter', streakCounter);
        return streakCounter;
    } else {
        return 0;
    }
}

更新:这似乎不是一个承诺,所以我需要以不同的方式格式化它(作为回调)。当我尝试这个时:

async function checkUserCommitForDate(user, date) {
    const options = {
        url: `https://api.github.com/search/commits?q=author:${user}+author-date:${date}`,
        headers: {
            'User-Agent': 'request',
            'Accept': 'application/vnd.github.cloak-preview'
        }
    };
    request(options, async function (error, response, body) {
        console.log('error:', error); // Print the error if one occurred
        if (JSON.parse(body).total_count > 0) {
            const previousDaysDate = moment(date).subtract(1, 'day').format('YYYY-MM-DD');
            let streakCounter = await checkUserCommitForDate(user, previousDaysDate);
            streakCounter++;
            console.log('streakCounter', streakCounter);
            return streakCounter;
        } else {
            return 0;
        }
    });
}

线

let streakCounter = await checkUserCommitForDate(user, previousDaysDate);

成为问题,因为streakCounter 未定义,导致日志NaN

【问题讨论】:

  • 您是否使用request 模块,而不是response?如果是这样,它不会返回一个承诺,而是使用回调。
  • 什么是 gitubResponse?你有没有在尝试解析之前 console.log 它?
  • 在更新中,当我记录正文时,我得到 JSON,当我解析它时,我得到一个对象,我仍然没有返回数字,因为有一个新问题。
  • 我不认为您可以将 await/async 与回调一起使用,它们与 Promises 一起使用。请求包使用回调,这使得 async/await 无法使用,因为您无法从回调中真正返回任何内容。
  • "所以我需要用不同的格式(作为回调)。" - 不,所以你需要为此做出承诺。或者只使用request-promise 包而不是request

标签: node.js asynchronous recursion async-await node-request


【解决方案1】:

如果您升级到 Node 8 LTS,则可以使用原生 util.promisfy,如下所示:

const { promisify } = require('util')
const request = promisify(require('request'))

async function checkUserCommitForDate(user, date) {
  const options = {
    url: `https://api.github.com/search/commits?q=author:${user}+author-date:${date}`,
    headers: {
      'User-Agent': 'request',
      'Accept': 'application/vnd.github.cloak-preview',
      'json':true
    }
  };

  try{
    const githubResponse = await request(options);
    if (githubResponse.body.total_count > 0) {
      const previousDaysDate = moment(date).subtract(1, 'day').format('YYYY-MM-DD');
      let streakCounter = await checkUserCommitForDate(user, previousDaysDate);
      streakCounter++;
      console.log('streakCounter', streakCounter);
      return streakCounter;
    } else {
        return 0;
    }
  }
  catch(err){
    console.error(err)
    return 0;
  }
}

options 中使用 json:true,将减少另一个解析步骤,因为响应将采用 JSON 格式。

【讨论】:

    【解决方案2】:

    正如 cmets 中所说的 request 使用回调而不是返回一个承诺,而且你真的不需要自己承诺它,因为已经有一个名为 request-promise 的包。

    在您的代码中使用它应该直接使用 async/await 开箱即用

    【讨论】:

      【解决方案3】:

      我从这里使用promisify example 将其转换为这个并且它有效!

      async function checkUserCommitForDate(user, date) {
          const options = {
              url: `https://api.github.com/search/commits?q=author:${user}+author-date:${date}`,
              headers: {
                  'User-Agent': 'request',
                  'Accept': 'application/vnd.github.cloak-preview'
              }
          };
      
          const githubResponse = await promisify(request)(options);
      
          if (JSON.parse(githubResponse.body).total_count > 0) {
              const previousDaysDate = moment(date).subtract(1, 'day').format('YYYY-MM-DD');
              let streakCounter = await checkUserCommitForDate(user, previousDaysDate);
              streakCounter++;
              console.log('streakCounter', streakCounter);
              return streakCounter;
          } else {
              return 0;
          }
      }
      
      function promisify(fn) {
          return function (...args) {
              return new Promise((resolve, reject) => {
                  fn(...args, (err, result) => {
                      if (err) return reject(err);
                      resolve(result);
                  });
              });
          };
      };
      

      【讨论】:

      • 已经有一个 request-promise (github.com/request/request-promise) 模块可以处理您的请求承诺
      • 感谢恩里克!如果您想在其中创建一个答案,我会将其标记为正确的。
      猜你喜欢
      • 2018-02-09
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 1970-01-01
      • 2018-01-28
      • 1970-01-01
      • 2020-02-14
      相关资源
      最近更新 更多