如何从 Nodejs 的 HTTPS GET 请求返回响应?

Joh*_*art 2 javascript asynchronous node.js

我还在学习node.js,所以请友善。

在没有打开书本的情况下,我正在努力理解一些基础知识。

我编写了一个函数来从 URL 获取一些 JSON。这是可行的,但我如何从函数返回数据,然后挑选位。这是我的代码。SerialNumber 是返回的 JSON 元素之一。

const https = require('https');

function authenticate( uuid , cdcloc ) {
    let url = cdcloc + "/api.php?uuid=" + uuid + '&auth';
    https.get(url,(res) => {
        let body = "";
        res.on("data", (chunk) => {
            body += chunk;
        });
        res.on("end", () => {
            try {
                let cdcResponse = JSON.parse(body);
                // do something with JSON
                return cdcResponse[0];
            } catch (error) {
                console.error(error.message);
            };
        });
    }).on("error", (error) => {
        console.error(error.message);
    });
}
const connection = authenticate( 'DATATOBEPASSED' , 'https://URLHERE');
console.log(connection.SerialNumber);
Run Code Online (Sandbox Code Playgroud)

Tha*_*you 5

节点式回调

O.Jones 的答案是正确的,但它违反了 Node 的错误优先回调约定https.get我认为每次需要提出请求时都去联系也是一个错误。这是一个低级函数,因为它要求您连接如此多的零散部分,所以您很可能会犯一些很容易避免的错误。

我们可以编写一个通用getString函数来包装https.get-

const https = require('https')

function getString(url, options, callback)
{ https
    .get(url, options, res => {
      let s = "";
      res.on("data", d => s += d)
      res.on("end", _ => callback(null, s) // error-first callback
    })
    .on("error", e => callback(e))         // error-first callback
}
Run Code Online (Sandbox Code Playgroud)

现在我们有了一个获取字符串的通用函数,我们不需要在每个发出请求的函数中编写res.on("data, ...)and 。res.on("end", ...)但不要停在这里。您经常会想要JSON.parse结果 -

function getJSON(url, options, callback)
{ getString(url, options, function(err, data)
  { if (err) callback(err)                         // getString error
    else try { callback(null, JSON.parse(data) }   // JSON.parse success
    catch (e) { callback(e) }                      // JSON.parse error
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以编写代码,authenticate而无需接触裸露的内容https.get或担心每次解析 JSON -

function authenticate(uuid, cdcloc, callback)             // callback
{ const url = cdcloc + "/api.php?uuid=" + uuid + '&auth'
  getJSON(url, {}, function(err, json)
  { if (err)
      callback(err)                                       // getJSON error
    else if (json.length == 0)
      callback(Error("empty response"))                   // empty response error
    else
      callback(null, json[0])                             // success
  }
}
Run Code Online (Sandbox Code Playgroud)

承诺

但这一切仍然很痛苦,不是吗?输入承诺。节点式回调是在我们无法访问异步控制流原语的时候设计的。从那时起我们已经走了很长一段路。为了了解 Promise 是如何工作的,我们将重新实现上面的函数,但这一次不需要到处传递回调和错误检查 -

const https = require('https')

function getString(url, options)           // no callback
{ return new Promise((resolve, reject) =>  // return Promise
  { https
      .get(url, options, res => {
        let s = "";
        res.on("data", d => s += d)
        res.on("end", _ => resolve(s))     // success, resolve
      })
      .on("error", e => reject(e))         // failure, reject
  }
}
Run Code Online (Sandbox Code Playgroud)

当我们重写时,我们立即看到新实现的好处getJSON-

function getJSON(url, options = {})   // no callback
{ return getString(url, options)      // return promise
    .then(s => JSON.parse(s))         // errors auto bubble up
}
Run Code Online (Sandbox Code Playgroud)

当我们写作时还有更多好处authenticate-

function authenticate(uuid, cdcloc)                   // no callback
{ const url = `${cdcloc}/api.php?uuid=${uuid}&auth`
  return getJSON(url)                                 // return promise
    .then(data => {
      if (data.length == 0)
        throw Error("empty response")                 // local error
      else
        return data[0]                                // success
    })                                                // no error-check
}
Run Code Online (Sandbox Code Playgroud)

异步/等待

即使 Promise 也已经存在很长时间了,自从它们原生包含在 ECMAScript 中以来,我们已经学到了很多东西。请记住返回承诺并且必须通过调用对所有数据进行排序.then是乏味的,就像编写这些初始值res.on("data", ...)res.on("end", ...)处理程序的感觉一样。asyncawait关键字允许我们使用异步控制流,而不必牺牲同步编程风格 -

async function getJSON(url, options = {})   // async
{ const s = await getString(url, options)   // await
  return JSON.parse(s)                      // auto wrapped in Promise
}
Run Code Online (Sandbox Code Playgroud)

写作authenticate很简单,感觉很自然——

async function authenticate(uuid, cdcloc)                 // async 
{ const url = `${cdcloc}/api.php?uuid=${uuid}&auth`
  const data = await getJSON(url)                         // await
  if (data.length == 0)
    throw Error("empty response")                         // throw if empty
  else
    return data[0]                                        // return first
}
Run Code Online (Sandbox Code Playgroud)

使用起来很简单,感觉也很自然 -

async function connect()
{ const connection = await authenticate( 'DATATOBEPASSED' , 'https://URLHERE')
  console.log(connection.SerialNumber)
  // ...
  return "done"                            // or whatever
}

connect().then(console.log, console.error) // errors bubble all the way up
Run Code Online (Sandbox Code Playgroud)

网址

我还应该提到,使用字符串连接构建 URL 非常乏味,并且容易出现许多错误。您应该对这种疼痛产生一种感觉,并知道这意味着有缓解的空间。看一下URL 模块,它可以以几乎所有可以想象的方式安全地构建/操作 URL。