首頁 > web前端 > js教程 > Promises/A 和非同步等待 - JavaScript 挑戰

Promises/A 和非同步等待 - JavaScript 挑戰

Barbara Streisand
發布: 2024-11-04 15:02:34
原創
626 人瀏覽過

Promises/A  & Async await - JavaScript challenges

您可以在倉庫 Github 上找到本文中的所有程式碼。


非同步編程 Promises/A & Async 等待相關挑戰


使用 Promise.finally() 實作 Promises/A

class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onFulfilledCallbacks.forEach((callbackFn) => callbackFn(this.value));
      }
    } 

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach((callbackFn) => callbackFn(this.reason));
      }
    }

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

  handlePromiseResult(result, resolve, reject) {
    if (result instanceof MyPromise) {
      result.then(resolve, reject);
    } else {
      resolve(result);
    }
  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function'
      ? onFulfilled
      : (value) => value;
    onRejected = typeof onRejected === 'function'
      ? onRejected
      : (reason) => { throw reason; };

    // return a promise
    return new MyPromise((resolve, reject) => {
      const fulfilledHandler = () => {
        queueMicrotask(() => {
          try {
            const result = onFulfilled(this.value);
            this.handlePromiseResult(result, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      };

      const rejectedHandler = () => {
        queueMicrotask(() => {
          try {
            const result = onRejected(this.reason);
            this.handlePromiseResult(result, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      };

      if (this.state === 'fulfilled') {
        fulfilledHandler();
      } else if (this.state === 'rejected') {
        rejectedHandler();
      } else {
        this.onFulfilledCallbacks.push(fulfilledHandler);
        this.onRejectedCallbacks.push(rejectedHandler);
      }
    });
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(onFinally) {
    if (typeof onFinally !== 'function') {
      return this.then();
    }

    return this.then(
      (value) => MyPromise.resolve((onFinally()).then(() => value)),
      (reason) => MyPromise.resolve(onFinally()).then(() => { throw reason })
    );
  }

  static resolve(value) {
    return new MyPromise((resolve) => resolve(value));
  }

  static reject(reason) {
    return new MyPromise((_, reject) => reject(reason));
  }
}

// Usage example
const promise = MyPromise.resolve(1);
promise.then((value) => {
  console.log(value);
})
.then(() => {
  throw new Error('Error');
})
.catch((err) => {
  console.log(`Error catched: ${err}`);
});
登入後複製

使用生成器實現異步等待

function asyncGenerator(generatorFunc) {
  return function (...args) {
    const generator = generatorFunc(...args);

    return new Promise((resolve, reject) => {
      function handle(iteratorResult) {
        if (iteratorResult.done) {
          resolve(iteratorResult.value);
          return;
        }

        Promise.resolve(iteratorResult.value)
          .then(
            (value) => handle(generator.next(value)),
            (err) => handle(generator.throw(err)),
          );
      }

      try {
        handle(generator.next());
      } catch (err) {
        reject(err);
      }
    });
  }
}

// Usage example
function* fetchData() {
  const data1 = yield fetch('https://jsonplaceholder.typicode.com/posts/1').then(res => res.json());
  console.log(data1);

  const data2 = yield fetch('https://jsonplaceholder.typicode.com/posts/2').then(res => res.json());
  console.log(data2);
}

// Create an async version of the generator function
const asyncFetchData = asyncGenerator(fetchData);

// Call the async function
asyncFetchData()
  .then(() => console.log('All data fetched!'))
  .catch(err => console.error('Error:', err));
登入後複製

參考

  • 67。創建你自己的 Promise - BFE.dev
  • 123。實作 Promise.prototype.finally() - BFE.dev
  • 承諾 - MDN
  • 非同步函數 - MDN
  • 承諾/A

以上是Promises/A 和非同步等待 - JavaScript 挑戰的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板