Q - Javascript承诺等待数组填充

时间:2014-12-19 09:41:53

标签: javascript asynchronous q

我是Q库的新手,我对Q对数组方法的承诺有所了解。 我有一个数组,其中各种键字符串将被延迟函数替换。 传入的数组成功替换后,我需要继续使用现在已经完成的数组。 在这种情况下,如何等待替换阵列?

输出看起来像

 key: "p", 
 text: "Good morning %text%", 
 inside:  key: "p"
          text: "Good afternoon user"
          inside: key: "p"
                  text: "This user has to be replaced."

正如您所看到的,并非所有按键都被替换了。

代码示例

var object = [];
    object.key = "p";
    object.text = "Good morning %text%";
    object.inside = [];
    object.inside.key = "p";
    object.inside.text = "Good afternoon %text%";
    object.inside.inside = [];
    object.inside.inside.key = "p";
    object.inside.inside.text = "This %text% has to be replaced.";

goDeep(object, 0);

console.log(object);

function goDeep(data) {
    if (data instanceof Object) {
        Object.keys(data).forEach(function(key) {
            if (data[key] instanceof Object) {
                goDeep(data[key]);
            } else if (data[key].inside) {
                goDeep(data[key].inside);
            } else {
                var match = scanText(data[key]);
                if (match && !(match instanceof Boolean)) {
                    getServerData(match.input).then (function(response) {
                        var splitData = data[key].match(/%.*%/)[0].split(",");
                        for (ii = 0; ii < splitData.length; ++ii) {
                            splitData[ii] = splitData[ii].trim();
                            var replaceData = data[key].replace(splitData[ii], response);
                            // Data gets replaced here
                            data[key] = replaceData;
                        };
                    });
                }
            }
        });
    }
}

function scanText(data) {
    var match = data.match("(%.*%)", "/g");
    if (match) {
        return match;
    } else {
        return false;
    }
}

function getServerData(data) {
    return Q.delay(1000).thenResolve("user");
}

1 个答案:

答案 0 :(得分:2)

首先让我稍微纠正你真正想要的东西,

使用JavaScript承诺递归调用异步函数

  
    

注意:我注意到 Q 库,但我相信它会与其他承诺实施类似

  

我会尽力简化您的问题,以便逐步解释

1。如何将一系列承诺变为单一承诺

您需要all方法

Q.all([
 getWeather({name:'beirut'}),
 getWeather({name:'paris'}),
 getWeather({name:'madrid'})
]).then(function(beirut, paris, madrid){
 // here I am sure that the 3 methods where completed
});

2。如何将参数数组转换为promises数组

使用array.map

['beirut', 'paris', 'madrid'].map(function(city){ return getWeather(city) });

3。实现递归机制

function getWeather(area) {
    // this function should return a promise of the weather response
    var deferred = Q.defer();
    setTimeout(function () {
        deferred.resolve({
            name: 'beirut',
            children: [{
                name: 'sub area'
            }, ...]
        });
    }, 300);

    return deffered.promise;
}

function resolveChildren(parentArea, level) {
    var deferred = Q.defer();

    getWeather(parentArea).then(function (children) {
        var promise = Q.all(children.map(function ( /* a sub area */ child) {
            // if this a leaf then resolve the child, else go deeper and get the children of this child
            // suppose child.isleaf return true if this is a leaf node
            if (child.isleaf) {
                return child;
            }

            return resolveChildren(child, level + 1);
        }));

        promise.then(function (children) {
            parentArea.children = children;
            deferred.resolve(parentArea);
        });
    }, function (err) {
        // failed to get children for some reason
        parentArea.children = null;
        deferred.resolve(parentArea);
    });

    return deffered.promise;
}