如何使用非常规方法从NodeJS中的异步函数传递数据?

Log*_*gan 2 javascript asynchronous node.js

我一直在玩jsdom,这是node.js的一个模块.底部的以下代码来自其文档页面.我的问题是如何从异步函数返回一些东西.

我知道这个问题很多,可能也是我的问题.我也知道,当涉及到这类问题时,回调是一个好朋友.我的目标是在PHP中找到一个可能像cookie或Session变量一样的解决方法,以便在异步函数之外将这一小部分数据传输到外部作用域.然后,一旦从外部范围设置数据,就应该可以访问它.

我想知道的第一件事是:

  1. 是否已经有办法将数据存储在外部作用域中存在的cookie或会话中,并且在我完成了必须执行的操作后可以访问?
  2. 如果我要将数据写入文件,在代码中的B点,并在C点读取,那么在读取文件之前,我是否不得不编写某种超时函数等待几秒钟?我在nodejs中使用异步函数的经验有时表明我必须在写入过程完成之前等待几秒钟才能尝试读取它.这也是这种情况吗?如果是的话,这是不是意味着如果我保存数据的地方就是内存呢?
  3. 如果我是为了这个目的而编写一个c ++插件,它就像一个单独的数据托架,我们可以save(data)B点到内存,从Cretrieve(data)点到内存; 这会有用吗?

老实说,我不喜欢编写临时文件来解决异步函数.我一直在寻找一种简单而有效的方法来传递数据,但是我需要像你这样有经验的程序员的一些指导来超越这个问题的不必要的方法.

如果你能为我提出一些想法,说明哪些可行,哪些可能无效,我会很感激.

这是示例代码:

// 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)
Run Code Online (Sandbox Code Playgroud)

Pet*_*ons 7

您需要清除您的同步体验,认为文件中较低的代码会在以后发生.它不一定在节点中那样做.这是交易.在节点中,您可以像在餐馆一样下订单,而不是像以下那样:

1. Order a salad
2. Wait 11 minutes
3. Eat the salad
Run Code Online (Sandbox Code Playgroud)

你这样做

1. Order a salad
2. Wait for the server to serve you the salad
3. Eat the salad
Run Code Online (Sandbox Code Playgroud)

第一个例子是一个竞争条件和你的程序中的一个可怕的错误,将导致沙拉等待无缘无故地吃或尝试吃不存在的沙拉.

不要想"我想在这里回复一些东西",认为"这个数据准备就绪".所以你可以:

function eatSalad() {...}
placeOrder("salad", eatSalad);
Run Code Online (Sandbox Code Playgroud)

例程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);
}
Run Code Online (Sandbox Code Playgroud)

编辑添加以从注释中回答您的问题,节点代码通常不是从返回事物的函数构建的,而是从调用具有"返回值"的回调函数的函数构建的.该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);
    });;
}
Run Code Online (Sandbox Code Playgroud)

这就是你做事的方式.通常这样的函数执行非常有限数量的IO调用(1或2是常见的,然后你开始陷入嵌套地狱并需要重构).

我亲自编写了许多这样的函数,然后使用异步库来描述需要发生的高阶序列.还有很多其他流行的流控制库,有些人喜欢promises模式.然而,目前一些核心节点社区成员似乎主张回调作为一种真正的方式,而承诺似乎正在失宠.