节点 - 如何等待异步操作? [英] Node - how to wait on async operations?

查看:204
本文介绍了节点 - 如何等待异步操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不好意思,刚开始使用的节点。这可能是一个非常初级的问题。

Sorry, just starting with node. This might be a very novice question.

让我们说我有一些code其内容在文件系统中的目录中的一些文件:

Let's say I have some code which reads some files from a directory in the file system:

var fs = require('fs');

fs.readdir(__dirname + '/myfiles', function (err, files) {
    if (err) throw err;
    files.forEach(function (fileName) {
        fs.readFile(__dirname + '/myfiles/' + fileName, function (err, data) {
            if (err) throw err;
            console.log('finished reading file ' + fileName + ': ' + data);
            module.exports.files.push(data);
        });
    });
});

请注意,所有这一切异步发生。让我们也说我有一个摩卡测试,执行此code:

Note that all of this occurs asynchronously. Let's also say I have a Mocha test which executes this code:

describe('fileProvider', function () {
    describe('#files', function () {
        it.only('files array not empty', function () {
            assert(fileProvider.files.length > 0, 'files.length is zero');
        });
    });
});

摩卡测试完成的文件读取之前运行。我知道这是因为我看到的console.log语句之后我看到小圆点,表示摩卡测试正在运行(至少我认为这是被什么指示)。另外,如果我周围的断言用的setTimeout,断言通过。

The mocha test runs before the files are finished being read. I know this because I see the console.log statement after I see the little dot that indicates a mocha test being run (at least I think that is what is being indicated). Also, if I surround the assert with a setTimeout, the assert passes.

我应该如何构建我的code,这样我可以保证操作完成异步文件?请注意,这不只是一个测试的问题 - 我需要的文件被完全加载之前,我可以在我的应用程序做实事,以及

How should I structure my code so that I can ensure the async file operations are completed? Note that this is not just a problem with testing - I need the files to be loaded fully before I can do real work in my app as well.

我不认为正确的答案是同步读取文件,因为这将阻止节点请求/响应循环,对吧?

I don't think the right answer is to read files synchronously, because that will block the Node request / response loop, right?

奖金的问题:结果
即使我把断言中的setTimeout以0超时值,测试还通过。这是因为这样的文件系统工作完成最初只是把它在一个setTimeout的它踢的处理链什么的末端?

Bonus question:
Even if I put the assert in a setTimeout with a 0 timeout value, the test still passes. Is this because just putting it in a setTimeout kicks it to the end of the processing chain or something so the filesystem work finishes first?

推荐答案

中的所有文件都被读取后,可以实现一个完整的回调。

You can implement a complete callback after all files have been read.

exports.files = [];
exports.initialize = initialize;

function initialize(callback) {
    var fs = require('fs');

    fs.readdir(__dirname + '/myfiles', function (err, files) {
        if (err) throw err;
        files.forEach(function (fileName) {
            fs.readFile(__dirname + '/myfiles/' + fileName, function (err, data) {
                if (err) throw err;
                console.log('finished reading file ' + fileName + ': ' + data);
                exports.files.push(data);
                if (exports.files.length == files.length) {
                    callback();
                }
            });
        });
}

您可以通过做一些像调用文件操作方法:

You can call the file operation method by doing something like:

var f = require('./files.js');

if (f.files.length < 1) {
    console.log('initializing');
    f.initialize(function () { 
        console.log('After: ' + f.files.length);

        var another = require('./files.js');
        console.log('Another module: ' + another.files.length);
    });
}

修改:既然你想只需要一次调用该方法,可以初始化加载应用程序时一次。据 Node.js的文档,模块在加载后的第一时间缓存。上面两个例子已被编辑为好。

EDIT: Since you want to only have to call this once, you could initialize it once when the application loads. According to Node.js documentation, modules are cached after the first time they are loaded. The two above examples have been edited as well.

这篇关于节点 - 如何等待异步操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆