手作業でpeomiseを実装する

Promises / A +仕様

最新のJavaScriptインフラストラクチャの一部として、Promiseはフロントエンド開発者にとって非常に重要です。

これは、async / await構文の基礎であり、JavaScriptで非同期を処理する標準形式です。さらに、将来のWeb APIは、非同期である限り、Promisesの形式で表示されます。

Promisesの知識と操作メカニズムを理解していないと、将来的にWeb開発の日常業務を完了できなくなる可能性があります。

したがって、Promisesは、フロントエンドのインタビューで必ず尋ねる質問の1つになっています。インターネットでは、多くのPromises技術記事を検索することもできます。セールスポイントとしてPromises / A +仕様を最初から実装する方法を教えるフロントエンドの有料チュートリアルもあります。

Promisesをすでに理解している開発者にとって、Promises / A +の実装は有用なトレーニングです。

予備作業

健全で相互運用可能なJavaScriptのオープンスタンダード

用語を理解する

1.1 “promise” is an object or function with a then method whose behavior conforms to this specification.
1.2 “thenable” is an object or function that defines a then method.
1.3 “value” is any legal JavaScript value (including undefined, a thenable, or a promise).
1.4 “exception” is a value that is thrown using the throw statement.
1.5 “reason” is a value that indicates why a promise was rejected.

仕様の最初の部分では、いくつかの用語の意味について説明しています。

promiseは、仕様で指定された動作に準拠するthenメソッドを含むオブジェクトまたは関数です。

Thenableは、thenとオブジェクトまたは関数を含むメソッドです。

valueは、正当なJS値です。

例外は、throwステートメントによってスローされる値です。

reasonは、promiseが拒否された理由を示す値です。

約束のステータス

A promise must be in one of three states: pending, fulfilled, or rejected.

2.1 When pending, a promise:
  2.1.1 may transition to either the fulfilled or rejected state.
2.2 When fulfilled, a promise:
  2.2.1 must not transition to any other state.
  2.2.2 must have a value, which must not change.
2.3 When rejected, a promise:
  2.3.1 must not transition to any other state.
  2.3.1 must have a reason, which must not change.

約束には3つの状態があり、それらは保留中、履行済み、および拒否されます。

保留状態では、promiseを履行または拒否に切り替えることができます。

フルフィルド状態では、他の状態に移行することはできず、不変の値を持っている必要があります。

拒否された状態では、別の状態に移行することはできず、不変の理由が必要です。

次にメソッド

A promise must provide a then method to access its current or eventual value or reason.

A promise’s then method accepts two arguments:

promise.then(onFulfilled, onRejected)

promiseには、onFulfilledパラメーターとonRejectedパラメーターを受け入れるthenメソッドが必要です。

onFulfilledのパラメーターはvalueであり、onRejected関数のパラメーターはreasonです。

const PENDING = 'PENDING'
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'

class Promise {
    
    
  constructor(executor) {
    
      // 执行器
    this.status = PENDING
    this.value = undefined
    this.reason = undefined

    let resolved = (value) => {
    
    
      if (this.status === PENDING) {
    
    
        this.value = value
        this.status = RESOLVED
      }
    }

    let rejected = (reason) => {
    
    
      if (this.status === PENDING) {
    
    
        this.reason = reason
        this.status = REJECTED
      }
    }

    try {
    
    
      executor(resolved, rejected)
    } catch (e) {
    
    
      rejected(e)
    }
  }
  then(onFulfilled, onRejected) {
    
    
    if (this.status === RESOLVED) {
    
    
      onFulfilled(this.value)
    }
    if (this.status === REJECTED) {
    
    
      onRejected(this.reason)
    }
  }
}

非同期状況の処理

class Promise {
    
    
  constructor {
    
    
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    let resolve = (value) => {
    
    
      if (this.status === PENDING) {
    
    
        this.value = value;
        this.status = RESOLVED;
        this.onFulfilledCallbacks.forEach(fn => fn()); // 订阅
      }
    }

    let reject = (reason) => {
    
    
      if (this.status === PENDING) {
    
    
        this.reason = reason;
        this.status = REJECTED;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    }

    try {
    
    
      executor(resolve, reject);
    } catch (e) {
    
    
      reject(e);
    }
  }

  then(onFulfilled, onRejected) {
    
    
    let promise2 = new Promise((resolve, reject) => {
    
    
      if (this.status === RESOLVED) {
    
    
        // 根据x的值来判断promise2的状态
        setTimeout(() => {
    
    
          let x = onFulfilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        }, 0);
        
      }
      if (this.status === REJECTED) {
    
    
        onRejected(this.reason);
      }
      // 处理异步的情况
      if (this.status === PENDING) {
    
     //发布订阅模式
        this.onFulfilledCallbacks.push(() => {
    
    
          onFulfilled(this.value);
        })
        this.onRejectedCallbacks.push(() => {
    
    
          onRejected(this.reason);
        })
      }
    })
    return promise2;
  }
}

約束の解決手順

[外部リンク画像の転送に失敗しました。元のサイトにヒル防止リンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-pQiIDhqv-1614052331001)(…/…/ .vuepress / public / img / promise .jpg)]

最初のステップで、結果が現在のプロミス自体である場合、TypeErrorがスローされます。

2番目のステップでは、結果が別の約束である場合、その状態と結果の状態が使用されます。

結果がthenableオブジェクトである場合の3番目のステップ。最初にthen関数を取得し、次にthen関数を呼び出して、Promise ResolutionProcedureプロセスに再度入ります。

const resolvePromise = (promise2, x, resolve, reject) => {
    
    
  if (promise2 === x) {
    
    
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>]'));
  }
  if(typeof x === 'object' && x !== 'null' || typeof x === 'function') {
    
    
    try {
    
    
      let then = x.then;
      if (typeof then === 'function') {
    
    
        then.call(x, y => {
    
    
          resolve(y);
        }, r => {
    
    
          reject(r);
        })
      }
    } catch (e) {
    
    
      reject(e);
    }
    let then = x.then;
  } else {
    
    
    resolve(x);
  }
}

総括する

手作業で約束を実行できることは、約束に習熟するのに役立ちません。Promise / A +仕様は、実装方法に焦点を当てています。使い方ではありません。

約束に習熟したい場合は、日々の開発のさまざまな非同期シナリオについて、より多くのことを考え、訓練する必要があります。

おすすめ

転載: blog.csdn.net/Beth__hui/article/details/113979969