Javascript 如何使用非常规方法在NodeJS中通过异步函数传递数据?
我一直在玩jsdom,它是node.js的一个模块。下面底部的代码来自他们的文档页面。我的问题是如何从异步函数返回一些东西 我知道这是一个被问了很多的问题,可能也是我问的。我也知道,当遇到此类问题时,回电是一个好朋友。我在这里的目标是找到一个类似于PHP中的cookie或会话变量的解决方法,以便将少量数据传输到异步函数之外的外部作用域。然后,一旦从外部范围设置了数据,就应该可以访问它 我想知道的第一件事是:Javascript 如何使用非常规方法在NodeJS中通过异步函数传递数据?,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我一直在玩jsdom,它是node.js的一个模块。下面底部的代码来自他们的文档页面。我的问题是如何从异步函数返回一些东西 我知道这是一个被问了很多的问题,可能也是我问的。我也知道,当遇到此类问题时,回电是一个好朋友。我在这里的目标是找到一个类似于PHP中的cookie或会话变量的解决方法,以便将少量数据传输到异步函数之外的外部作用域。然后,一旦从外部范围设置了数据,就应该可以访问它 我想知道的第一件事是: 是否已经有一种方法可以将数据存储在某个地方,比如存在于外部作用域中的cookie或会话,
// Print all of the news items on hackernews
var jsdom = require("jsdom");
// var result;
// A) Outer Scope: Since the function is async in done, storing the result here and echoing in point C is pointless.
jsdom.env({
html: "http://news.ycombinator.com/",
scripts: ["http://code.jquery.com/jquery.js"],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function() {
console.log(" -", $(this).text());
});
// B) let's say I want to return something I've scavenged here.
// result = $("a");
}
});
// C)
// console.log(result)
您需要清除您认为文件中较低的代码稍后会发生的同步体验。它不一定在node中这样做。事情是这样的。在node中,您可以像在餐厅一样下订单,而不是像以下那样:
1. Order a salad
2. Wait 11 minutes
3. Eat the salad
你是这样做的
1. Order a salad
2. Wait for the server to serve you the salad
3. Eat the salad
第一个例子是一个竞赛条件和程序中的一个可怕的错误,它会导致等待的沙拉无缘无故地被吃掉,或者试图吃掉一个还没有出现的沙拉
不要认为“我想在这里归还一些东西”,而应该认为“这些数据已经准备好了”。因此,您可以:
function eatSalad() {...}
placeOrder("salad", eatSalad);
其中,eatSalad
是placeOrder
例程的回调,该例程执行必要的I/O以获取沙拉。请注意,即使文件中的eatSalad
在前面,它也是按时间顺序在后面发生的。您不返回东西,而是使用准备好的数据调用回调
这是异步生成的代码片段
// Print all of the news items on hackernews
var jsdom = require("jsdom");
// var result;
// A) Outer Scope: Since the function is async in done, storing the result here and echoing in point C is pointless.
jsdom.env({
html: "http://news.ycombinator.com/",
scripts: ["http://code.jquery.com/jquery.js"],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function() {
console.log(" -", $(this).text());
});
// B) let's say I want to return something I've scavenged here.
// result = $("a");
resultIsReady($("a"));
}
});
function resultIsReady(element) {
console.log(element);
}
编辑以添加根据注释回答您的问题,节点代码通常不是从返回内容的函数中生成的,而是从使用“返回值”调用回调函数的函数中生成的。return
关键字仅用于实际返回不执行任何I/O操作的内存中代码的值。因此,查找内存中数组的平均值只能返回该值,但从数据库结果集中查找平均值必须调用回调函数。基本范例是通过以下函数构建程序(伪代码数据库库):
这就是你做事的方式。通常,像这样的函数执行的IO调用数量非常有限(1或2是常见的,然后您开始陷入嵌套地狱,需要重构)
我个人编写了很多这样的函数,然后使用库来描述需要发生的事情的高阶序列。还有很多其他流行的流控制库,一些人喜欢promises模式。然而,目前一些核心节点社区成员似乎主张回调是一种真正的方式,承诺似乎不受欢迎。避免在可能阻碍执行的任何地方使用同步代码,如数据库操作、文件IO、网络数据检索、长时间计算等。 在您的示例中,当您完成计算以继续执行时,您还可以查看async library,它实际上是更复杂调用的标准:
function sendData(result) {
res.json(result);
}
var jsdom = require("jsdom");
// var result;
// A) Outer Scope: Since the function is async in done, storing the result here
// and echoing in point C is pointless.
jsdom.env({
html: "http://news.ycombinator.com/",
scripts: ["http://code.jquery.com/jquery.js"],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function () {
console.log(" -", $(this).text());
});
// B) let's say I want to return something I've scavenged here.
var result = $("a");
sendData(result);
}
});
同步世界:服务员接受你的订单,去厨房,等待你的订单,把它带给你,然后去接另一个订单。异步世界:服务员为您点菜,然后去厨房,再去点菜,等菜好了再给您拿菜。谢谢您的回答!它向我展示了为什么人们最终会在嵌套函数中得到一个混乱的嵌套。。。我想我的想法更像PHP或C#,在那里我可以更加集中。我的意思是写很多不同的小函数,它们返回一些东西,然后用在食物链中较大的函数中,控制较小的函数并返回一组结果。这种方法的名称是什么?我应该远离这种思维方式吗?有什么建议吗?再次感谢您的更新。你的回答非常密集,内容丰富。它让我对Node.js中应该规划的代码结构有了基本的了解。然而,你最后的陈述让我感到好奇。对回调的一般反对意见是什么?为什么它似乎不受欢迎?你能提供的任何资料都会对我的研究有所帮助。这是一个非常热门的文化话题。我认为这在很大程度上是因为Ryan Dahl设计的核心节点API是基于回调的,而不是
function sendData(result) {
res.json(result);
}
var jsdom = require("jsdom");
// var result;
// A) Outer Scope: Since the function is async in done, storing the result here
// and echoing in point C is pointless.
jsdom.env({
html: "http://news.ycombinator.com/",
scripts: ["http://code.jquery.com/jquery.js"],
done: function (errors, window) {
var $ = window.$;
console.log("HN Links");
$("td.title:not(:last) a").each(function () {
console.log(" -", $(this).text());
});
// B) let's say I want to return something I've scavenged here.
var result = $("a");
sendData(result);
}
});