2

次のようなことを避けるために、ネストされた関数呼び出しをうまく行う方法を探していました。

var result = function1(function2(function3()));

または次のようなもの:

var result = function3();
result = function2(result);
result = function1(result);

Unix からの配管のようなものがいいでしょう:

var result = function3() | function2() | function1();

ソース: https://www.npmjs.com/package/babel-plugin-operator-overload

もちろん|、ビットごとの or 演算です。この例は抽象的です。

トランスパイルせずに、ES5、ES6、または ES7 を使用してこのような効果を達成する方法を知っている人はいますか?

編集

TJ Crowder さん、虎三郎さん、Bergi さん、ありがとうございました。皆さんの回答には、ユニークで有益で興味深い情報が含まれていました。

4

3 に答える 3

4

ヘルパー関数なし

最初はヘルパー機能なしでこれを行うという質問を受けましたが、その後のコメントはそうではないことを示唆しています。ヘルパー関数がスコープ内にある場合は下にスキップします。

ヘルパー関数を追加しなくても、ES6 promise を使用できます。

Promise.resolve()
    .then(function3)
    .then(function2)
    .then(function1)
    .then(result => {
  console.log("result is " + result);
});

それはよりきれいではありません

var result = function1(function2(function3()));

...しかし、少なくとも呼び出される関数は呼び出された順序でリストされており、promise は複数の点で非常に柔軟です。

例: Babel の REPL のライブコピー

function function1(arg) {
  console.log("function1 called with " + arg);
  return "result1";
}
function function2(arg) {
  console.log("function2 called with " + arg);
  return "result2";
}
function function3() {
  console.log("function3 called");
  return "result3";
}

Promise.resolve()
    .then(function3)
    .then(function2)
    .then(function1)
    .then(result => {
  console.log("result is " + result);
});

出力:

関数 3 が呼び出されました
function2 が result3 で呼び出される
function1 が result2 で呼び出されました
結果はresult1

ヘルパー機能付き

あなたのコメントについて:

function pipe(){
    var str = 'Promise.resolve()';
    for(var i = 0; i < arguments.length; i++){
        str += '.then(arguments[' + i + '])'
    }
    eval(str);
}

 pipe(c, b, a, result => { console.log("result is " + result); });

パイプは fs ライブラリにあることを知っているので、関数名はあまり良くありません。それとは別に、これに明らかな問題はありますか?

これでヘルパー関数をスローしたい場合、 はまったく必要ありませんeval。約束されていない関数の場合は、次のようにします。

function pipe(first, ...more) {
  return more.reduce((r, f) => f(r), first());
}

let result = pipe(function3, function2, function1);

Babel の REPL でのライブコピー

promise 化された関数またはミックスでこれを行いたい場合は、次のようにします。

function pipe(...functions) {
  return functions.reduce((p, f) => p.then(f), Promise.resolve());
}

次に、あなたが示した方法でそれを呼び出すことができます:

pipe(function3, function2, function1, result => {
    // ...
});

...しかし、そうするとエラーが無視されます。最後の約束を返すのでpipe、すべての約束の良さを利用できます

pipe(function3, function2, function1, result => {
    // ...
}).catch(failure => {
    // ...
});

また

pipe(function3, function2, function1)
    .then(result => {
        // ...
    })
    .catch(failure => {
        // ...
    });

単純な関数と promise を返す関数を組み合わせた完全な例を次に示します。 Babel の REPL のライブ コピー

function pipe(...functions) {
    return functions.reduce((p, f) => p.then(f), Promise.resolve());
}
function function1(arg) {
    console.log("function1 called with " + arg);
    return "result1";
}
function function2(arg) {
    console.log("function2 called with " + arg);
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("result2");
        }, 100);
    });
}
function function3() {
    console.log("function3 called");
    return "result3";
}

pipe(function3, function2, function1)
    .then(result => {
        console.log("Final result is " + result);
    })
    .catch(failure => {
        console.log("Failed with " + failure);
    });

出力:

関数 3 が呼び出されました
function2 が result3 で呼び出される
function1 が result2 で呼び出されました
最終結果はresult1
于 2015-11-08T08:09:45.520 に答える
4

関数を作成しているだけです。compose多くのライブラリで利用可能な関数を使用するか、独自に作成して、次のように使用します。

compose(function1, function2, function3) ()

つまり、「パイプ」演算子は、compose の呼び出しでパラメーターを区切るために使用される「コンマ」と考えることができます。

これは本当に単純な構成です:

function compose(...fns) {
  var lastFunc = fns.pop();
  return function() { 
    return fns.reduceRight(result, fn) {
      return fn(result);
    }, lastFunc(...arguments));
  };
}
于 2015-11-08T11:10:44.353 に答える
1

あなたが探しているのは、pipe基本的によく知られているcompose反転された関数です。

var result = pipe(function3, function2, function1)();

これは組み込みではありません (また、今後の ES リビジョンのいずれにも予定されていません) が、Ramdaなどの多くのライブラリで利用できます。自分で簡単に実装できます:

function pipe(g, ...fs) {
    if (!arguments.length) return x => x;
    if (!fs.length) return g;
    const f = pipe(...fs);
    return x => f(g(x));
}

新しい構文を探している場合は、言語にパイプライン シュガーをもたらす可能性のある ES7 の提案があります。正確にはどのようになるかはまだ決まっていません

method3()::method2()::method1()
method3()->method2()->method1()
function3()->function2()->function1()
于 2015-11-08T11:40:48.397 に答える