【问题标题】:How to properly check and log http status code using promises and node.js?如何使用 Promise 和 node.js 正确检查和记录 http 状态代码?
【发布时间】:2018-08-03 02:37:09
【问题描述】:

我是 JavaScript 新手,对 node.js 框架非常陌生,几天前才开始使用它。如果我的代码是荒谬的,我深表歉意,承诺和回调的整个想法仍然深入人心。话虽如此,我的问题是以下我试图弄清楚对网站的某些请求是否成功或导致错误的范围他们的状态码响应。我正在处理一系列网站,到目前为止我所做的工作如下,但是我在安装了 node.js 的本地计算机上得到了TypeError: Cannot read property 'then' of undefined,但不知道为什么。

const sample = [
    'http://www.google.com/',
    'http://www.spotify.com/us/',
    'http://twitter.com/',
    'http://google.com/nothing'
]

const http = require('http')

const getStatusCodeResult = (website) => {

    http.get(website, (res) => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                let statusCode = res.statusCode
                error = statusCode >= 400 && statusCode <= 500 ? `error: ${website}`: null
                if (error) {
                    reject(error)
                    
                } else if (statusCode >= 200 && statusCode <= 300) {
                    resolve(`Success: ${website}`)
                }
            }, 0)
        })
    })
}
// LOOP PROMISES
const getAllStatusCodeResult = (websites) => {
    websites.forEach((website) => {
        getStatusCodeResult(website)
            .then((result) => {
                console.log(result)
            })
            .catch(error => {
                console.log('error', error)
            })
    })
}
getAllStatusCodeResult(sample)

理想情况下,我希望将结果打印为下面的示例,但现在我只是使用console.log 来确定代码是否有效。

   // Example Printout
   {
      success: ['https://www.google.com/', 'https://www.spotify.com/us/', 
      'https://twitter.com /' ],
      error: [''http://google.com/nothing']
   } 

【问题讨论】:

    标签: javascript node.js callback promise es6-promise


    【解决方案1】:

    你混淆了前两行。为您获取返回值的 new Promise 包装器需要位于外部,而 http.get 调用应位于其执行器回调中。你也不需要那个超时:

    function getStatusCodeResult(website) {
        return new Promise((resolve, reject) => {
            http.get(website, (res) => {
                let statusCode = res.statusCode,
                    error = statusCode >= 400 && statusCode <= 500 ? `error: ${website}`: null
                if (error) {
                    reject(error)
                } else if (statusCode >= 200 && statusCode <= 300) {
                    resolve(`Success: ${website}`)
                }
            })
        })
    }
    

    【讨论】:

    • 太棒了,你能解释一下为什么承诺包装http.get 是它一直使用的方式你用承诺包装引用环境吗?另外,你有没有机会知道为什么我只收到error error: http://google.com/nothing Success: http://www.google.com/ 而不是其他网站。
    • 是的,您总是将异步函数包装在 new Promise 构造函数中。你解决和拒绝的方式通常不同
    • 如果你没有从其他承诺中得到任何东西,很可能响应既不是 400
    • @Bergi 使用util.promisify() 添加解决方案对我有好处吗?还是我不应该打扰?
    • @Bergi 你认为我应该发布一个不同的问题,关于不记录示例数组中的所有站点只记录http://google.com/nothing http://www.google.com/
    【解决方案2】:

    使用util.promisify(),您可以将http.get()转换为基于promise的异步方法,但首先需要做一些准备,因为它不遵循callback(error, response) { ... }的约定:

    const http = require('http')
    const { promisify } = require('util')
    
    // define a custom promisified version of `http.get()`
    http.get[promisify.custom] = (options) => new Promise(resolve => {
      http.get(options, resolve)
    });
    
    // convert callback to promise
    const httpGet = promisify(http.get)
    
    async function getStatusCodeResult(website) {
      const res = await httpGet(website)
      const status = res.statusCode
      const message = `${http.STATUS_CODES[status]}: ${website}`
    
      if (status >= 400) {
        throw message
      } else {
        return message
      }
    }
    

    此外,您可以使用http.STATUS_CODES 为每个可能的statusCode 获取适当的消息,而不是返回模糊的ErrorSuccess

    【讨论】:

    • 我想知道,http.get[promisify.custom] 不应该已经是节点中的本机了吗?
    • @Bergi 我检查了,它没有定义。
    猜你喜欢
    • 1970-01-01
    • 2019-11-03
    • 2011-08-31
    • 2010-12-26
    • 2020-04-05
    • 2012-09-15
    • 2023-03-02
    • 1970-01-01
    • 2012-12-22
    相关资源
    最近更新 更多