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)
节点式回调
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", ...)处理程序的感觉一样。async和await关键字允许我们使用异步控制流,而不必牺牲同步编程风格 -
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。