安全な割り当て

WBOY
WBOYオリジナル
2024-09-10 14:30:15511ブラウズ

Safe Assignment

今日は、JavaScript における安全な代入演算子 (?=) の新しい提案についてかなり話題になりました。私は JavaScript が時間の経過とともに改善されてきたことを気に入っていますが、これは最近いくつかのケースで遭遇する問題でもあります。関数として簡単な実装例を作成する必要がありますね?

この提案をまだ読んでいない場合は、提案内容を以下に示します。

const [error, value] ?= maybeThrows();

新しい ?= 演算子は、try/catch ブロック内の代入の右側を呼び出して配列を返すのと同じになります。代入内で何かがスローされた場合、返される配列の最初の値はエラーとなり、何もスローされなかった場合、2 番目の値は代入の結果になります。

よくあるトライ/キャッチの煩わしさ

私は、代入ブロックや try/catch ブロックの周りで非常に醜いコードに頻繁に遭遇します。このようなもの:

let errorMsg;

try {
  maybeThrow();
} catch (e) {
  errorMsg = "An error message";
}

try/catch ブロックの外側で errorMsg にアクセスするには、const を使用するか、ブロックの外側で定義する必要があります。

非同期の実装

ここでの最も簡単なケースは、非同期関数を処理することです。ムチムチできました
いくつかのテストケースと tryCatch という関数をすぐに実行できます:

function tryCatch(fn, ...args) {
  try {
    return [undefined, fn.apply(null, args)]
  } catch (e) {
    return [e, undefined];
  }
}

function throws() {
  throw new Error("It threw");
}

// returns a sum
// prints [ undefined, 2 ]
console.log(tryCatch(Math.sqrt, 4));

// returns an error
// prints [ Error: 'It threw', undefined ]
console.log(tryCatch(throws));

tryCatch は、try/catch ブロックでラップされた指定された引数を使用して関数を呼び出します。関数内で何もスローされない場合は適切に [未定義、結果] を返し、何かがスローされる場合は [エラー、未定義] を返します。

呼び出す関数がまだない場合は、tryCatch で匿名関数を使用することもできることに注意してください。

console.log(tryCatch(() => {
  throw new Error("It threw");
}));

非同期関数の処理

非同期関数は少し複雑になります。私が最初に考えていたアイデアの 1 つは、
と書くことでした。 完全に非同期のバージョンは、おそらく asyncTryCatch と呼ばれるものですが、その課題はどこにありますか。これは全く無意味な探索です!以下は、非同期関数と非同期関数の両方で動作する tryCatch の実装です。

function tryCatch(fn, ...args) {
  try {
    const result = fn.apply(null, args);

    if (result.then) {
      return new Promise(resolve => {
          result
            .then(v => resolve([undefined, v]))
            .catch(e => resolve([e, undefined]))  
      }); 
    }

    return [undefined, result];
  } catch (e) {
    return [e, undefined];
  }
}

function throws() {
  throw new Error("It threw");
}

async function asyncSum(first, second) {
  return first + second;
}

async function asyncThrows() {
  throw new Error("It throws async");
}

// returns a sum
// prints [ undefined, 2 ]
console.log(tryCatch(Math.sqrt, 4));

// returns an error
// prints [ Error: 'It threw', undefined ]
console.log(tryCatch(throws));

// returns a promise resolving to value
// prints [ undefined, 3 ]
console.log(await tryCatch(asyncSum, 1, 2));

// returns a promise resolving to error
// prints [ Error: 'It throws async', undefined ]
console.log(await tryCatch(asyncThrows));

オリジナルのバージョンとよく似ていますが、Promise ベースのコードがいくつか含まれています
念のため投入。この実装を使用すると、非同期関数を呼び出すときに tryCatch を呼び出し、非同期関数を呼び出すときに await tryCatch を呼び出すことができます。

Promise ビットを見てみましょう:

if (result.then) {
  return new Promise(resolve => {
      result
        .then(v => resolve([undefined, v]))
        .catch(e => resolve([e, undefined]))    
  }); 
}

if (result.then) は、指定された関数 (apply で呼び出された) が Promise を返したかどうかを確認します。そうなった場合は、自分で Promise を返す必要があります。

result.then(v =>solve([undependent, v])) を呼び出すと、何もスローされない場合、Promise は指定された関数が返した値に解決されます。

.catch(e =>solve([e, unknown])) は少し複雑です。最初に書いたのは
.catch(e =>reject([e, unknown])) となりますが、捕捉されないエラーが発生します
tryCatch から外れます。
を返すため、ここで解決する必要があります。 配列、エラーはスローされません。

そして最後に

私はかなり定期的に、試したり捕まえたりする必要があるが、次のように感じることがあります
明示的な try/catch ブロックは大量のスペースを占有し、スコープ指定の割り当てにとって煩わしいものになります。使うかどうかは分かりませんが、ちょっとした探検で楽しかったです。

以上が安全な割り当ての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。