我一直在玩jsdom,这是node.js的一个模块。底部的以下代码来自其文档页面。我的问题是如何从异步函数返回一些东西。
我知道这是一个很多问题,可能也是我。我也知道,当涉及到这类问题时,回调是一个好朋友。我的目标是在PHP中找到一个可能像cookie或Session变量一样的解决方法,以便在异步函数之外将这一小部分数据传输到外部作用域。然后,一旦从外部范围设置数据,就应该可以访问它。
我想知道的第一件事是:
save(data)
来自记忆的点 C ;这会有用吗?老实说,我不喜欢编写临时文件来解决异步函数问题。我一直在寻找一种简单而有效的方法来传递数据,但是我需要像你这样有经验的程序员的一些指导来超越这个问题的不必要的方法。
如果你能为我提出一些想法,说明哪些可行,哪些可能无效,我会很感激。
以下是示例代码:
retrieve(data)
答案 0 :(得分:7)
您需要清除您的同步体验,认为文件中较低的代码会在以后发生。它不一定在节点中那样做。这是交易。在节点中,您可以像在餐馆一样下订单,而不是像以下那样:
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的内存中代码的值。因此,找到内存数组的平均值只能返回它,但是从数据库结果集中找到均值必须调用回调函数。基本范例是从像这样的函数(伪代码DB库)构建你的程序:
function getUser(email, callback) {
db.users.where({email: email}, function (error, user) {
if (error) {
//This return statement is just for early termination
//of the function. The value returned is discarded
return callback(error);
}
callback(null, user);
});;
}
这就是你做事的方式。通常这样的函数执行非常有限数量的IO调用(1或2是常见的,然后你开始陷入嵌套地狱并需要重构)。
我亲自编写了许多这样的函数,然后使用async库来描述需要发生的高阶序列。还有很多其他流行的流控制库,有些人喜欢promises模式。然而,目前一些核心节点社区成员似乎主张回调是一种真正的方式,而承诺似乎已经失宠。
答案 1 :(得分:3)
避免在可能阻止执行的任何地方使用同步代码,例如数据库操作,文件IO,网络数据检索,长时间计算等。 在您的示例中,在完成计算以继续执行时使用回调,您还可以查看异步https://npmjs.org/package/async库,这是毛发调用的事实标准:
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);
}
});