만약 억지로 async 함수로 동기화를 처리하려고 한다면 매우 번거로울 것이다

12966 단어 JavaScriptasynctech
이 프로젝트가 다음 대상 고리의 구조를 구축했을 때.
(단순화)
const objectPool = {
  _pool: [],

  // parentプロパティがnullのオブジェクトを取得
  pick() {
    return this._pool.find(obj => obj.parent == null);
  },
  
  // pickを非同期的に処理する
  async pickAsync() {
    const obj = this.pick();
    if (obj) {
      return obj;
    } else {
      throw null;
    }
  },
  
  // プールにオブジェクトを追加
  add(obj) {
    this._pool.push(obj)
  }
};
여러분의 주의가 필요한 것은pickAssync 방법입니다.이 비동기 처리에 대한 오해로 걸려 넘어졌다.기술적으로는 버튼이 잘못 걸린 수준이지만 마음의 공급을 위해 보도화한다.
그럼 pickAsync, async 함수 내return과Promise.resolve, throw 및 Promise에 해당합니다.리퀘스트에 해당하는 처리로 되돌아와 수영장에서 적당한 대상을 찾을 수 있는 상황과 찾지 못할 경우 처리가 유창하게 쓰일 수 있다.
// 子オブジェクトクラス
class ChildObject {

  constructor() {
    this.parent = null;
  }

  setParent(parent) {
    this.parent = parent;
  }
}

// 仮の親オブジェクト
const dummyParent = {};

// プールに4コオブジェクトを補充
for (let i = 0; i < 4; i++) {
  objectPool.add(new ChildObject());
}

// オブジェクトをプールから拾う
objectPool.pickAsync()
  .then(obj => {
    // 適当なオブジェクトが見つかった場合の処理
    obj.setParent(dummyParent);
  })
  .catch(e => {
    // 見つからなかったときの処理
    console.warn("見つかりませんでした");
  });
이것은 단일 처리에서 예상한 대로 조작하였으나 조립이 순환 중일 때 문제가 발생하였다.
for (let i = 0; i < 8; i++) {
  objectPool.pickAsync()
    .then(obj => {
      obj.setParent(dummyParent);
    })
    .catch(e => {
      console.warn("見つかりませんでした");
    })
}
피지의 대상이 4개밖에 없기 때문에 앞부분을 4번 순환하면 then측 처리이고 뒷부분은 4번은catch측 처리이지만 실제로는 모두then측 처리이다.그리고 모든 순환은 같은 대상을 선택했다.
이유는 간단하다. 비동기 함수의 처리는 정지 상태일 뿐 순환을 중단하지 않고 순환 후 시간차에 따라 실행되기 때문이다.
상기 예에서 같은 대상의 setParent 순환을 8번 실행합니다.
이걸 알아차리면 아니, 당연한 거지...?이런 오류였지만 편리한 탓에 동기식 처리였던 비동기식 처리라 도무지 이상한 점을 알아채지 못했다.
(서버 통신 등 처리 내용이 좀 비동기적이라면 금방 알아볼 수 있을 텐데...)
이외에도 비슷한 전철을 밟고 수영장의 행동이 예상대로 순조롭게 진행되지 않아 고민이 생기는 시간 등을 처리Promise.all하는 문제도 있었다.
동기화 순환에 비동기 처리를 넣는 것을 추천하지 않습니다.
본 세션의 샘플 코드:
https://runstant.com/pentamania/projects/46b08148

경품:async상태를 유지하여 동시 순환 처리


나중에 for-await...of 모드를 사용하면 동기 순환 처리를 할 수 있다는 것을 알게 되었다.
(async function() {
  // 8回pick
  // number -> iterableへの変換は Array-likeへの変換で行う
  for await (let i of Array.from({length: 8})) {
    ObjectPool.pickAsync()
    .then((item)=> {
      item.setParent(dummyParent)
    })
    // 見つからなかったときの処理
    .catch((err)=> console.error(err))
  }
})();
이것은 async 함수로 묶어야 하고 순환 횟수의iterable 변환이 필요합니다. 약간 미묘하지만 참고로만...
샘플 코드

좋은 웹페이지 즐겨찾기