bugfix> javascript > 投稿

なぜそれはまさに resolve 約束が正しく someOtherPromise を待つ完了しますが、 reject ではない?次のコードサンプルを実行し、console.logの出力を確認します。 「myPromiseが解決しました」と同様に、「myFailingPromiseが拒否されました」というメッセージが2000ミリ秒後に表示されると予想していました。

let someOtherPromise = (previousPromise) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(previousPromise + ' => someOtherPromise after 2000ms');
      resolve('someOtherPromise');
    }, 2000);
  });
}
let myPromise = () => {
  return new Promise((resolve, reject) => {
    resolve(someOtherPromise('myPromise'));
  });
};
let myFailingPromise = () => {
  return new Promise((resolve, reject) => {
    reject(someOtherPromise('myFailingPromise'));
  });
};
myPromise().then((val) => {
  // this is executed after `someOtherPromise` resolves.
  console.log('myPromise resolved');
}).catch((err) => {
  console.log('myPromise rejected');
});
myFailingPromise().then((val) => {
  // this is executed after `someOtherPromise` resolves.
  console.log('myFailingPromise resolved');
}).catch((err) => {
  console.log('myFailingPromise rejected');
});

someOtherPromise.then(reject) を使用することで意図した動作を実現できることを知っています2番目の例では、しかし、私の質問は、なぜ reject の引数としての約束 resolve で機能するため、不可能です。 。

回答 3 件
  • 約束Aを解決するときに、それを解決する値が約束Bである場合、約束Aは約束Bの状態と一致します。

    ただし、約束を拒否する場合は、その理由が約束のように見えるかどうかに関係なく、あなたが唯一の理由を与えます。

    あなたがする必要があるのは、 someOtherPromise で解決することです  両方の場合において。

    とにかく最初の約束を待って拒否したい場合、これを行うことができます:

    let myFailingPromise = () => {
      return new Promise((resolve, reject) => {
        someOtherPromise.then(reject);
      });
    };
    
    

  • 拒否は reason のみを受け取ります  エラーを強調表示します。別の約束ではありません。同じタイプの別のプロミスでプロミスを解決できますが、最後のプロミスの成功ケースのみが表示されます。

    この適応された実装を見てください:

    const someOtherPromise = new Promise((resolve, _) => {
        resolve("I am a success");
    });
    const failingPromise = new Promise((_, reject) => {
        reject("I failed for a reason");
    });
    someOtherPromise
        .then((result) => {
                console.log("some other promise resolves", result);
                failingPromise
                    .then((success) => {
                        console.log("never called");
                    })
                    .catch((reason) => {
                        console.error("failing promise rejects", reason);
                    });
            }
        )
        .catch((error) => {
            console.error("also never called", error);
        });
    
    

    これは then です -コールバック地獄につながる他の約束を待つための可能なアプローチ。これが、async/await構文も使用できる理由です。

    const app = async () => {
            try {
                const success1 = await someOtherPromise; // will succeed
                console.log(success1);
                const success2 = await failingPromise; // never succceds
                console.log(success2); // never be reached
            } catch (e) {
                return Promise.reject(e); // catches the error of failing promise and rethrows it, redundant but here showcases error handling
            }
        }
    ;
    app()
        .then(() => {
            console.log("never be reached because of failing promise");
        })
        .catch(console.error);
    
    

  • タイムアウト付きの更新された質問に関して、常に別の約束を待つためにできることは次のとおりです。

    const otherPromise = async (willBeSuccesful: boolean) => {
        console.log("started timer for case", willBeSuccesful);
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log("resolve timer for case", willBeSuccesful);
                const successValue = "Fnord"; // whatever you want
                return willBeSuccesful
                    ? resolve(successValue)
                    : reject("this other promise failed because of reasons"); // only provide a reason, not another promise
            });
        };
    };
    const alwaysWaitForOtherPromiseThenRejectAnyway = async (otherPromise) => {
        try {
            const success = await otherPromise; // always waits 2 seconds, not matter
            console.log("other promises succeeded with value", success);
        } catch (e) {
            return Promise.reject(e); // passing through reason, redundant, only to showcase
        }
        return Promise.reject("reason why this promise failed"); // only happens after otherPromise was resolved, you could swallow that error and fail here or resolve here as well
    };
    const succeedingPromise = otherPromise(true);
    const failingPromise = otherPromise(false);
    alwaysWaitForOtherPromiseThenRejectAnyway(succeedingPromise)
        .catch((reason) => console.error(reason)); // fail after waiting for success of other promise
    alwaysWaitForOtherPromiseThenRejectAnyway(failingPromise)
        .catch((reason) => console.error(reason)); // will fail as soon as otherPromise fails
    
    

    拒否が発生する前に、常にタイムアウトを待機します。拒否にはさまざまな理由があります。出力は次のようになります。

    started timer for case true
    started timer for case false
    resolve timer for case true
    resolve timer for case false
    other promises succeeded with value Fnord
    reason why this promise failed
    this other promise failed because of reasons
    
    

あなたの答え