Javascript顺序函数

时间:2018-01-29 13:19:15

标签: javascript closures sequence

我们需要按顺序运行一些javascript函数。这些函数存储在一个数组中:

m = [
  function(){...},
  function(){...},
  ...
  function(){...}
]

从第一个函数开始,使用初始参数运行它,并检查它是否返回Promise。如果没有,请将其包装在promise调用中并返回promise。

当promise被解决时,我们希望它运行下一个函数,参数是前一个函数的结果。

如果其中一个函数返回false,则停止执行并返回false

我是函数式编程的新手,我相信我在这里错过了一个核心概念。

TIA,

4 个答案:

答案 0 :(得分:4)

考虑



let seq = ps => ps.reduce((p, f) => p.then(x => x && f(x)), Promise.resolve(true));

a = [
    x => 'a',
    x => x + 'b',
    x => x + 'c',
];

seq(a).then(console.log.bind(console));

b = [
    x => 'a',
    x => false,
    x => x + 'c',
];

seq(b).then(console.log.bind(console));




答案 1 :(得分:1)

有点粗糙,但以下内容应该有效:

/**
 * Process array of functions and return a promise which will
 * contain the result of the last function, or false. 
 *  
 * @param  {Array} funcs - Array of functions to be called in sequence
 * @return {bool | mixed} - False, or return of last function
 */
const processFuncs = await (funcs) => {
    if( ! Array.isArray(funcs))
        return Promise.resolve(false);

    try{
        return await funcs.reduce( 
            async (res, f) => await res && f(...res);
        , true);
    }
    catch(err){
       return Promise.reject(err);
    }
}

这假定您的构建和/或目标支持ES6 +功能。

要使用OPs原始变量,只需调用:

const result = processFuncs(m); // Will be a promise which resolves to the return of the last function, or false

答案 2 :(得分:0)

我刚刚创建了fiddle作为预期行为的示例:它按顺序运行多个promise并在其中一个promises返回false时停止该序列(此外我编码返回一个带有当没有承诺返回错误时,承诺的结果。) 如果函数没有返回一个promise,而是另一个函数,后者将被包含在一个promise中,该promise将用函数的结果解析。

这是你的阵列:

let yourFunctionArray = [
    function() {
        return function() {
            return "hello"; //The promise resolution.
        };
    }
];

这是承诺所有承诺的承诺。

let work = new Promise(async function(resolve, reject) {
    let results = [];
    let _break = false;
    for (let array = yourFunctionArray, i = 0, l = array.length, f = array[i]; i < l; i++, f = array[i]) {
        if (_break)
            break;
        let promise = f();
        if (!promise) {
            reject();
            return;
        }
        if (!promise.then)
            promise = new Promise(function(resolve, reject) {
                resolve(promise());
            });
        await promise.then(async function(result) {
            if (result === false) {
                resolve(false);
                _break = true;
            } else
                results.push(result);
        });
    }
    resolve(results);
});

现在你可以运行这个承诺:

work.then(function(response) {
    alert("completed with " + response);
});

答案 3 :(得分:0)

这主要是对来自@supports at-ruleexcellent answer的一个小改动。

它允许您将多个参数传递给初始函数。它也会跳过他的假测试,我不太明白。处理多个参数使得它比底层let seq = ps => init => ps.reduce((p, f) => p.then(f), Promise.resolve(init))更复杂,因此除非有多个参数是真正可能的,否则它不值得使用。

&#13;
&#13;
let seq = ps => (...init) => ps.slice(1).reduce(
  (p, f) => p.then(f), 
  Promise.resolve(ps.length ? ps[0].apply(null, init) : init)
)

// Note that the first function takes multiple arguments

seq([
  (x, y) => x + y,
  x => x + 1,
  x => x * 2
])(3, 2).then(console.log)

// Functions can return Promises or plain values
// A Promise rejection is carried through

const foo = seq([
  x => Promise.resolve(x * 2),
  x => Promise.reject('oops'),
  x => x + 1
])

foo(5).then(console.info, console.error)
&#13;
&#13;
&#13;