javascript 如何使用 promises 和 node.js 正确检查和记录 http 状态代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48941063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 08:20:49  来源:igfitidea点击:

How to properly check and log http status code using promises and node.js?

javascriptnode.jscallbackpromisees6-promise

提问by Squanchy

I am new to JavaScript and very new to node.js framework, just started using it a few days ago. My apologies if my code is nonsensical, the whole idea of promises and callbacks is still sinking in. That being said my question is the following I am trying to figure out if certain request to websites are successful or cause an error based on the range of their status code response. I am working with an array of websites and what I've done so far is below, I do however get a TypeError: Cannot read property 'then' of undefinedon my local machine with node.js installed and can't figure out why.

我是 JavaScript 新手,也是 node.js 框架的新手,几天前才开始使用它。如果我的代码是荒谬的,我很抱歉,承诺和回调的整个想法仍在沉没。话虽如此,我的问题是以下我试图确定对网站的某些请求是否成功或导致基于范围的错误他们的状态码响应。我正在处理一系列网站,到目前为止我所做的如下所示,但是我确实TypeError: Cannot read property 'then' of undefined在安装了 node.js 的本地机器上获得了一个,但不知道为什么。

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)

Ideally I would want the result to be printed as the example below, but for now I am just using console.logto figure out if the code even works.

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

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

采纳答案by Bergi

You mixed up the first two lines. The new Promisewrapper that gets you the value to return needs to be on the outside, and the http.getcall should be inside its executor callback. Also you don't really need that timeout:

你混淆了前两行。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}`)
            }
        })
    })
}

回答by Patrick Roberts

Using util.promisify(), you can convert http.get()into a promise-based asynchronous method, but first there's some preparation to do since it does not follow the convention of callback(error, response) { ... }:

使用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
  }
}

In addition, you can use http.STATUS_CODESto get the the appropriate message for each possible statusCoderather than returning a vague Erroror Success.

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