与蓝鸟的承诺链数组

时间:2022-03-19 20:15:10

I'm a working my way with promises and I'm stuck with my use case. I have an array of transformer functions (each function is a promise and modifies some JSON structure).

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

Let me show some code.

让我展示一些代码。

Lets say this is my JSON structure (array)

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

var data = [{a: 1, b:2}, {a:3, b:4}]; 

transformFunction is definition of transform functions modifying the data a certain way. The two functions adds c and d property to the above JSON structure:

transformFunction是以某种方式修改数据的转换函数的定义。这两个函数将c和d属性添加到上面的JSON结构中:

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);
        })
    },
    ...
}

The from a UI user specifies which transformer functions he should use and in what order. Lets say he picked the normal order like this:

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

var userTransformList = ['transform1', 'transform2'];

The transform1 method should modify the data and the result should be passed to transform2 method.

transform1方法应该修改数据,结果应该传递给transform2方法。

I was looking at: Promise.all but it seems that it does not care for the order of the promises, and most important it needs to pass the previous result to the next promise.

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

2 个解决方案

#1


5  

Note: As adeneo pointed out in the comments, use promises only if you are dealing with asynchronous code.

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

  1. Create an array of functions which are to be executed. And make sure that they all return a Promise.

    创建要执行的函数数组。并确保他们都返回Promise。

  2. Then, you can use Promise.reduce to reduce the initial value to the transformed final value by returning the result of executing current promise returning function, on every iteration.

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

  3. Finally you can attach a then handler to get the actual value and a catch handler, just in case if the promises are rejected.

    最后,您可以附加一个then处理程序来获取实际值和一个catch处理程序,以防万一Promise被拒绝。

Lets say we have two transform functions like this.

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

Note: I am telling again. You should never use Promises with functions like these. You should use promises only when the functions you are dealing with are really asynchronous.

注意:我再说一遍。你永远不应该将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;
    }));
}

Then you can transform the original value, like this

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

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);
    });

Output

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

#2


4  

You can chain Promises the way you always do: using .then().

你可以像往常一样链接Promise:使用.then()。

Let's say you have these two transformations:

假设您有这两种转换:

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

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

In a real scenario, these would be doing asynchronous work. You could just:

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

increment(1).then(double)

But, you don't know the order or number of transformations. Let's put them into an array, and then() them one by one:

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

var transformations = [increment, double]

var promise = Promise.resolve(1);

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

You can attach a catch() handler before you start, after you finish or even per-transformation.

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

This isn't efficient if you're going to apply hundreds of transformations. In that case, you should use reduce() as thefourtheye suggests in his answer.

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

#1


5  

Note: As adeneo pointed out in the comments, use promises only if you are dealing with asynchronous code.

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

  1. Create an array of functions which are to be executed. And make sure that they all return a Promise.

    创建要执行的函数数组。并确保他们都返回Promise。

  2. Then, you can use Promise.reduce to reduce the initial value to the transformed final value by returning the result of executing current promise returning function, on every iteration.

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

  3. Finally you can attach a then handler to get the actual value and a catch handler, just in case if the promises are rejected.

    最后,您可以附加一个then处理程序来获取实际值和一个catch处理程序,以防万一Promise被拒绝。

Lets say we have two transform functions like this.

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

Note: I am telling again. You should never use Promises with functions like these. You should use promises only when the functions you are dealing with are really asynchronous.

注意:我再说一遍。你永远不应该将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;
    }));
}

Then you can transform the original value, like this

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

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);
    });

Output

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

#2


4  

You can chain Promises the way you always do: using .then().

你可以像往常一样链接Promise:使用.then()。

Let's say you have these two transformations:

假设您有这两种转换:

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

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

In a real scenario, these would be doing asynchronous work. You could just:

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

increment(1).then(double)

But, you don't know the order or number of transformations. Let's put them into an array, and then() them one by one:

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

var transformations = [increment, double]

var promise = Promise.resolve(1);

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

You can attach a catch() handler before you start, after you finish or even per-transformation.

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

This isn't efficient if you're going to apply hundreds of transformations. In that case, you should use reduce() as thefourtheye suggests in his answer.

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