尝试使用Q.js循环遍历文件

时间:2014-06-21 19:22:42

标签: javascript jquery asynchronous q

我正在尝试使用Q.js来处理网络应用中promisesdeferrable的一些问题 - 我首先会说我对async的理解基本上是0现在。这是我第一次真正尝试过,即使在阅读了尽可能多的文档之后,我仍然非常

以前使用名为 jsdeferred 的库来完成以下代码;它遍历文件列表并加载它们,并将它们添加到数组中。但我已经知道我不应该使用jsdeferred 而且我被告知应该使用 promises {{1} } 正确。

我已经为此探讨了很多场所,我可能只是愚蠢,但我很难在面向Promises的库中实现这个确切的代码(在这个例子中,我试图使用{{1} },没有成功)。

Q.js Library

deferrables

我特别难以使用文件加载/循环,任何帮助都将不胜感激。我想,一旦我站稳脚跟,我就能够做得更好,但是这个文件循环真的让我失望了。我在文档中继续阅读的所有内容似乎都是针对一次性使用场景。

我还在阅读文档,我将继续这样做,但如果有人能帮助我站稳脚跟,我将非常感激。一旦我看到它与我自己的东西一起工作,我就更容易接受其他情况。我还有大约20个我需要开始使用这个概念的地方,但这是第一个令我头疼的地方。

更新

我没有 使用 Q.js ,它只是最推荐的那个。如果它能解决我的问题,我也会看define(function () { return function (selector, callback) { var files = [ "/app_content/json/ecma5.json", "/app_content/json/jquery.json", "/app_content/json/tangent.json" ]; var results = []; var editor, server; return Deferred.loop(files.length, function (i) { return $.get(files[i]).next(function(data) { results.push(data); }); }).next(function () { // a lot of things happen here. they are amazing things. }).next(function() { // seriously, this stuff is awesome. }).next(function() { callback(editor); }); }; });

进一步更新

更多地使用文档,我合并了一些工作代码,但它似乎仍然缺少某些东西。我无法将Q.js作为参数传递给每个https://github.com/caolan/async,我必须将其保留为外部变量。

results

最终结果

在这里的每个人的帮助下,我终于让我的代码按照我想要的方式工作了。这是最终结果。这是使用 tern 和自定义脚本定义的 CodeMirror 的实现。

then(fn)

我非常感谢这里提供的建设性,有用,有用和知识渊博的信息。

3 个答案:

答案 0 :(得分:2)

试试这个

function readFile(file) {
    var deferred = Q.defer();
    $.get(file, function(data) {
         deferred.resolve(data);
    });
    return deferred.promise;
}

var promises = [];

var files = [
    "/app_content/json/ecma5.json",
    "/app_content/json/jquery.json",
    "/app_content/json/tangent.json"
];

for(var i = 0; i < files.length; i++){
    promises.push(readFile(files[i]));
}

Q.all(promises).spread(function(result1, result2, result3) {
    console.log(result1, result2, result3);
});

答案 1 :(得分:2)

使用Q.js,并假设您不需要随请求一起发送任何数据,您可以使用mapQ.all缩短代码:

var results,
    files = [
    "/app_content/json/ecma5.json",
    "/app_content/json/jquery.json",
    "/app_content/json/tangent.json"
];

Q.all(files.map($.get))
    .then(function(_results) {
        results = _results;
    })
    .then(function  () {
        // More awesome stuff here
    })
    .then(function () {
        // etc...
        console.log(results);
    })
    .done();

请注意,为了在后续results块中使用.then(),您必须在promise链之外保存对它的引用。在您的示例中,您想要的results对于您传递给then()的函数来说是本地的 - 它会影响全局results。只需给它一个不同的名称,例如_results,然后将其分配给全局results,以便以后能够使用它。

答案 2 :(得分:1)

我对你提到的the async library最熟悉,所以我将展示如何使用它。请参阅Q的其他答案。

您的代码的整体结构是您希望按顺序执行操作:一个接一个。所以:

async.series([
    function(callback) {
        // do something
    },
    function(callback) {
        // do something else
    },
    function(callback) {
        // and something else still
    }
], function(err) {
    // if err is set, an error occurred somewhere in the series
    // otherwise, all the above functions completed
});

这就是整体结构。现在,那个加载每个文件的东西怎么样?基本上,您希望从文件名映射到文件内容,而async可以轻松地异步映射:

async.map(files, function(file, callback) {
    jQuery.ajax({
        url: file,
        success: function(data) { return callback(null, data); },
        failure: function(err)  { return callback(err);        }
    });
}, function(err, fileData) {
    // if err is set, an error occurred while fetching one of the files
    // otherwise, fileData is an array with the file data
});

当然,您可以将此async.map调用嵌套到传递给async.series的任何函数中,这就是您如何构建这些小块,构建它们直到您完成整个工作流程