(翻译)ネストされたコールバックに対処し、「コールバック地獄」を回避する方法

(スラグスラグ少しモンスター翻訳、翻訳不幸なあなたが見ることができれば- > テキスト

jsが強力な言語です。時には、あなたは別のコールバックコールバックに対処する必要があり、これは、別のコールバックコールバックコールバックです。

人々は、このモデルのイメージがある記述コールバック地獄

これは、このようなビットです:

firstFunction(args, function() {
  secondFunction(args, function() {
    thirdFunction(args, function() {
      // And so on…
    });
  });
});
复制代码

これは、JSコールバックです。ネストされたコールバックのこのタイプを参照すると、それはあなたの脳は信じているが、私はこれがあるとは思わない「地獄。」あなたはそれに対処する方法を知っていれば、「地獄」よりよく管理することができることがあります。

コールバックについて

私はあなたが時間内に、この記事を読んで、コールバックの概念を知っていると仮定します。あなたがわからない場合は、この読み取りの記事を我々は、コールバックが何であるかを説明します。この記事を下るし続ける前に、。そこに、私たちは、コールバックがあり、なぜJavaScriptでそれらを使用するかを話し合います。

コールバック処理プログラム

これは、コールバック4つの処理プログラムの地獄です

  1. コメントを書きます
  2. 小さな機能に分割する機能
  3. 約束を使用してください
  4. 非同期が/待って使用します

我々は、このソリューションを説明分割する前に、私たちはコールバック地獄を構築しましょう。なぜ?それは本当にあまりにも抽象的なので、我々は:. FirstFunction上記の例を見ると、secondFuncitonとthirdFunctionは、私たちは本当に私たちの場合は、より具体的にするコールバックを構築してみましょう。

コールバック地獄を構築

今、我々は、我々が達成するために、次の手順を実行する必要がハンバーガーハンバーガーにするために行う必要があり、私たちが想像してみましょう:

  1. 食材の入手
  2. クッキング牛肉
  3. パンハンブルクを見ます
  4. 調理された牛肉は、パンの間に置きます
  5. サプライハンブルク

これらのステップが同期されている場合は、このような機能が表示されます。

const makeBurger = () => {
  const beef = getBeef();
  const patty = cookBeef(beef);
  const buns = getBuns();
  const burger = putBeefBetweenBuns(buns, beef);
  return burger;
};
const burger = makeBurger();
serve(burger);
复制代码

しかし、私たちの段階では、我々はあなた自身のバーガーを作ることができません。私たちは、ハンブルクのアシスタント製造工程を導く必要があります。私たちはアシスタントに指示した後、アシスタントは、我々は次のステップを開始する前に待たなければならない手順を実行します。

我々はJSに待っている途中で、再び実行したい場合は、我々はコールバックを使用する必要があります。ハンバーガーを作るために、我々は最初の牛肉を取得する必要があります。私たちは、牛肉を得た後、牛肉を調理することができます。

const makeBurger = () => {
  getBeef(function(beef) {
    // We can only cook beef after we get it.
  });
};
复制代码

牛肉、牛肉を調理するために、我々はそうでない場合、我々は調理する何かを持っていません。cookBeef関数に渡す必要があります。だから我々は、調理された牛肉を待たなければなりませんでした。

調理牛肉たら、私たちはパンを取得します

const makeBurger = () => {
  getBeef(function(beef) {
    cookBeef(beef, function(cookedBeef) {
      getBuns(function(buns) {
        // Put patty in bun
      });
    });
  });
};
复制代码

私たちはパンを取得した後、私たちはパンの2つのパンの間パテを配置する必要があります。これは、ハンブルクのどこ形成です。

const makeBurger = () => {
  getBeef(function(beef) {
    cookBeef(beef, function(cookedBeef) {
      getBuns(function(buns) {
        putBeefBetweenBuns(buns, beef, function(burger) {
            // Serve the burger
        });
      });
    });
  });
};
复制代码

最終的に、私たちはハンバーガーを提供することができます。それは非同期であるため、しかし、我々はmakeBurgerからハンバーガーを返すことはできません。私たちは、コールバックハンブルクを受信する必要があります。

const makeBurger = nextStep => {
  getBeef(function (beef) {
    cookBeef(beef, function (cookedBeef) {
      getBuns(function (buns) {
        putBeefBetweenBuns(buns, beef, function(burger) {
          nextStep(burger)
        })
      })
    })
  })
}
// Make and serve the burger
makeBurger(function (burger) => {
  serve(burger)
})
复制代码

このコールバックは、非常に興味深いああの例を作るために

解決方法1:コメントを書きます

このmakeBurgerコールバックはシンプルで理解しやすいです。私たちは読むことができます。それは良い見ていないが、いくつかがあります。

あなたが最初にこの機能makeBurgerを読めば、あなたは「なぜ私たちがハンバーガーを作るために非常に多くのコールバックが必要なのでしょうか?それは意味がない!」、思考することができます

この場合、あなたはあなたのコードを説明するためのコメントを残しておく必要があります。

// Makes a burger
// makeBurger contains four steps:
//   1. Get beef
//   2. Cook the beef
//   3. Get buns for the burger
//   4. Put the cooked beef between the buns
//   5. Serve the burger (from the callback)
// We use callbacks here because each step is asynchronous.
//   We have to wait for the helper to complete the one step
//   before we can start the next step
const makeBurger = nextStep => {
  getBeef(function(beef) {
    cookBeef(beef, function(cookedBeef) {
      getBuns(function(buns) {
        putBeefBetweenBuns(buns, beef, function(burger) {
          nextStep(burger);
        });
      });
    });
  });
};

复制代码

それを書くためにこの方法を使用する理由さて、あなたがこれを見たとき、私は、コールバック地獄を「WTF」を考えていないだろう、あなたは理解することができます。

解決方法2:別のコールバック関数に分割

コールバック地獄の例には、我々は偉大なスプリットの例を持っています。私がそう言う理由を理解し、私はあなたのコードを分割するステップバイステップを挙げてみましょう。

getBeef、私たちの最初のコールバックを取る、我々は牛肉を得るために冷蔵庫に行かなければなりませんでした。キッチン2台の冷蔵庫を持って、我々は冷蔵庫牛肉の右側を取る必要があります。

const getBeef = nextStep => {
  const fridge = leftFright;
  const beef = getBeefFromFridge(fridge);
  nextStep(beef);
};
复制代码

牛肉を調理するために、我々は、オーブンに牛肉を入れて200度にオーブンを開き、20分を待つ必要があります

const cookBeef = (beef, nextStep) => {
  const workInProgress = putBeefinOven(beef);
  setTimeout(function() {
    nextStep(workInProgress);
  }, 1000 * 60 * 20);
};
复制代码

今、あなたはmakeBurgerの各ステップを書かなければならなかった場合、この機能は非常に大きくなります想像してみてください。

具体的に小さい、コールバック関数に分割されますについて、あなたは私のコールバックの記事では、この小さな部分を読むことができます。

解決策3:使用の約束

私はあなたが約束が何であるかを知っている必要がありますね。あなたがわからない場合は、この1件の読んで記事を

むしろ、あなたがこのようなものが表示されます上記のネストされたコールバックよりも管理が容易なコールバック地獄を作ることを約束..:

const makeBurger = () => {
  return getBeef()
    .then(beef => cookBeef(beef))
    .then(cookedBeef => getBuns(beef))
    .then(bunsAndBeef => putBeefBetweenBuns(bunsAndBeef));
};
// Make and serve burger
makeBurger().then(burger => serve(burger));
复制代码

あなたは、単一のパラメータスタイルの約束を好む場合は、上記の本を例に変換することができます

const makeBurger = () => {
  return getBeef()
    .then(cookBeef)
    .then(getBuns)
    .then(putBeefBetweenBuns);
};
// Make and serve burger
makeBurger().then(serve);
复制代码

もっと読みやすく、管理。

しかし、問題は約束するコールバック地獄を変換する方法ですか?

約束へのコールバックターン

約束に変身するために、我々はその後、返すために、この約束を解決するために使用し、コールバックが正常に実行された各コールバックのための新たな約束を必要としています。コールバックがエラーを失敗したか、スローした場合や、我々は拒否を使用します。

const getBeefPromise = _ => {
  const fridge = leftFright;
  const beef = getBeefFromFridge(fridge);
  return new Promise((resolve, reject) => {
    if (beef) {
      resolve(beef);
    } else {
      reject(new Error(“No more beef!”));
    }
  });
};
const cookBeefPromise = beef => {
  const workInProgress = putBeefinOven(beef);
  return new Promise((resolve, reject) => {
    setTimeout(function() {
      resolve(workInProgress);
    }, 1000 * 60 * 20);
  });
};
复制代码

私たちの練習では、コールバック関数を記述する必要があります。あなたはノードを使用する場合は、コールバック関数を含むそれぞれが同じ構文を持つことになります。

  1. コールバック関数は、最後の引数になります
  2. コールバック関数は、2つのパラメータがあります。これらのパラメータは、(エラーが最初で、興味のあるものに続く)と同じ配列を有し
// The function that’s defined for you
const functionName = (arg1, arg2, callback) => {
  // Do stuff here
  callback(err, stuff);
};
// How you use the function
functionName(arg1, arg2, (err, stuff) => {
  if (err) {
  console.error(err);
  }
  // Do stuff
});
复制代码

すでにコールバックと同じ構文を持っている場合は、変換したり、約束するコールバックES6 Promisify Denodeifyのようなものを使用することができます。あなたは上記のノードV8.0またはを使用する場合は、util.promisify使用することができます。

それらのうち3つは使用することができます。あなたは、任意のライブラリを使用するように選択することができます。ただし、それぞれの方法の間の微妙な違いがあります。私はあなたがこの方法のためにそのドキュメントをチェックすることを示唆しています。

解決策4:関数は非同期使用しています(非同期/待っています)

非同期関数を使用するためには、最初の二つのことを知っておく必要があります。

  1. コールバックの約束を変換する方法(スリーは、当社のソリューションの内容と言いました)
  2. 非同期関数を使用する方法(ヘルプが必要な場合、あなたはこの読むことができる記事を

非同期関数を使用すると、同じ同期を書くように、makeBurgerを書くことができます!

const makeBurger = async () => {
  const beef = await getBeef();
  const cookedBeef = await cookBeef(beef);
  const buns = await getBuns();
  const burger = await putBeefBetweenBuns(cookedBeef, buns);
  return burger;
};
// Make and serve burger
makeBurger().then(serve);
复制代码

我々はmakeBurgerはここに改善することができます。あなたは、同時に2つのgetBunsとgetBeefアシスタントを得ることができます。これは、あなたがPromise.all構文を使用することができることを意味し、次に待っています。

const makeBurger = async () => {
  const [beef, buns] = await Promise.all(getBeef, getBuns);
  const cookedBeef = await cookBeef(beef);
  const burger = await putBeefBetweenBuns(cookedBeef, buns);
  return burger;
};
// Make and serve burger
makeBurger().then(serve);
复制代码

(:あなたは約束で同じ効果を行うことができますが、その構文は、/はそれほど明確待つ非同期とは違って、素晴らしいではありません注意してください。)

概要

あなたはとても恐ろしい想像どのようなコールバック地獄ません。コールバック地獄を管理するための4つの方法があります。

  1. コメントを書きます
  2. セグメンテーション機能小さな機能
  3. 約束を使用してください
  4. 非同期/のawait使用します

おすすめ

転載: blog.csdn.net/weixin_33801856/article/details/91377377