与蓝鸟的承诺链数组

时间:2015-06-09 13:05:40

标签: javascript arrays promise bluebird es6-promise

我正在以承诺的方式工作,我一直坚持使用我的用例。 我有一个变换器函数数组(每个函数都是一个promise并修改了一些JSON结构)。

让我展示一些代码。

让我们说这是我的JSON结构(数组)

for (var i = 0; i < title.length; i++) {
    title[i] = title[i].substring(0, 11); 
}

var data = [{a: 1, b:2}, {a:3, b:4}]; 是以某种方式修改数据的变换函数的定义。这两个函数将transformFunctionc属性添加到上面的JSON结构中:

d

来自UI用户指定他应该使用哪些变换器功能以及按什么顺序使用。让我们说他选择了这样的正常顺序:

var transformFunctions = { // 

    transform1: function (data) {  // This function adds `c` property to each object from `a`
        return new Promise(function (resolve) {
             for (var i = 0; i < data.length; i++) {
                 data[i].c = data[i].a;
             }
             return resolve(data);
        })
    },

    transform2: function (data) {  // This function adds `d` property to each object from `c`
        return new Promise(function (resolve) {
             for (var i = 0; i < data.length; i++) {
                 data[i].d = data[i].c;
             }
             return resolve(data);
        })
    },
    ...
}

var userTransformList = ['transform1', 'transform2']; 方法应该修改数据,结果应该传递给transform1方法。

我在看transform2但似乎它并不关心承诺的顺序,最重要的是它需要将之前的结果传递给下一个承诺。

2 个答案:

答案 0 :(得分:5)

注意:正如adeneo在评论中指出的那样,只有在处理异步代码时才使用promises。

  1. 创建要执行的函数数组。并确保他们都返回承诺。

  2. 然后,您可以使用Promise.reduce通过在每次迭代时返回执行当前承诺返回函数的结果来将初始值减少到已转换的最终值。

  3. 最后,您可以附加then处理程序以获取实际值和catch处理程序,以防万一承诺被拒绝。

  4. 假设我们有两个这样的变换函数。

    注意:我再说一遍。你永远不应该将Promises与这些函数一起使用。只有当你正在处理的函数真的是异步时才应该使用promises。

    // Just add a property called `c` to all the objects and return a Promise object
    function transform1(data) {
        return Promise.resolve(data.map(function(currentObject) {
            currentObject.c = currentObject.a + currentObject.b;
            return currentObject;
        }));
    }
    
    // Just add a property called `d` to all the objects and return a Promise object
    function transform2(data) {
        return Promise.resolve(data.map(function(currentObject) {
            currentObject.d = currentObject.a + currentObject.b + currentObject.c;
            return currentObject;
        }));
    }
    

    然后你可以转换原始值,就像这样

    Promise.reduce([transform1, transform2], function (result, currentFunction) {
            return currentFunction(result);
        }, [{a: 1, b: 2}, {a: 3, b: 4}])      // Initial value
        .then(function (transformedData) {
            console.log(transformedData);
        })
        .catch(function (err) {
            console.error(err);
        });
    

    <强>输出

    [ { a: 1, b: 2, c: 3, d: 6 }, { a: 3, b: 4, c: 7, d: 14 } ]
    

答案 1 :(得分:4)

您可以按照常规方式链接Promise:使用.then()

让我们说你有这两个转变:

function increment(x) {
    return Promise.resolve(x + 1);
}

function double(x) {
    return Promise.resolve(2 * x);
}

在实际场景中,这些将是异步工作。你可以:

increment(1).then(double)

但是,您不知道转换的顺序或数量。让我们把它们放到一个数组中,逐个then()

var transformations = [increment, double]

var promise = Promise.resolve(1);

for (var i = 0; i < transformations.length; i++)
  promise = promise.then(transformations[i]);

您可以在开始之前,完成之后或甚至每次转换之前附加catch()处理程序。

如果您要应用数百个转换,这不是有效的。在这种情况下,您应该使用reduce()作为 thefourtheye 在他的回答中建议。