programing

Promise의 처리 오류입니다.모든.

yoursource 2022. 10. 3. 22:27
반응형

Promise의 처리 오류입니다.모든.

는 지금 을하고 있습니다.Promise.all(arrayOfPromises);

나는 계속 약속의 사슬을 이어간다.이렇게 생겼네

existingPromiseChain = existingPromiseChain.then(function() {
  var arrayOfPromises = state.routes.map(function(route){
    return route.handler.promiseHandler();
  });
  return Promise.all(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
  // do stuff with my array of resolved promises, eventually ending with a res.send();
});

하고 싶은데, , ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★,Promise.all발견된 첫 번째 오류(나머지 무시)를 반환하고 배열 내의 나머지 약속에서 데이터를 가져올 수 없습니다(오류 없음).

나는 …과 같은 것을 하려고 했다.

existingPromiseChain = existingPromiseChain.then(function() {
      var arrayOfPromises = state.routes.map(function(route){
        return route.handler.promiseHandler()
          .then(function(data) {
             return data;
          })
          .catch(function(err) {
             return err
          });
      });
      return Promise.all(arrayOfPromises)
    });

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
      // do stuff with my array of resolved promises, eventually ending with a res.send();
});

하지만 그건 해결되지 않아요.

감사합니다!

--

편집:

아래의 답변은 완전히 사실이며, 다른 이유로 인해 코드가 깨지고 있습니다.혹시 관심 있는 분이 계실까 봐, 이게 제가 결국...

노드 익스프레스 서버 체인

serverSidePromiseChain
    .then(function(AppRouter) {
        var arrayOfPromises = state.routes.map(function(route) {
            return route.async();
        });
        Promise.all(arrayOfPromises)
            .catch(function(err) {
                // log that I have an error, return the entire array;
                console.log('A promise failed to resolve', err);
                return arrayOfPromises;
            })
            .then(function(arrayOfPromises) {
                // full array of resolved promises;
            })
    };

API 콜(route.async 콜)

return async()
    .then(function(result) {
        // dispatch a success
        return result;
    })
    .catch(function(err) {
        // dispatch a failure and throw error
        throw err;
    });

넣다.catch★★★★★★에Promise.allbefore .then는, 를 검출하는 으로 하고 있는 것 만, 그 후, 를 다음의 로 되돌립니다..then

감사합니다!

Promise.all전부 아니면 아무것도 아니야.어레이 내의 모든 약속이 해결되면 해결되거나 둘 중 하나가 거부되면 즉시 거부됩니다.즉, 해결된 모든 값의 배열로 해결되거나 단일 오류로 거부됩니다.

에는 어어 have have some have have have have have have have have have have have have have have some some some some some some 라는 것이 있습니다.Promise.when대신 어레이 내의 모든 약속이 해결되거나 거부될 까지 기다리지만 저는 잘 알지 못하고 ES6에도 없습니다.

고객님의 코드

당신의 수정이 효과가 있어야 한다는 다른 사람들의 의견에 동의합니다.성공한 값과 오류 개체가 혼재된 어레이를 사용하여 해결할 수 있습니다.성공 경로에서 오류 개체를 전달하는 것은 드문 일이지만 코드가 오류 개체를 예상하는 경우 문제가 없습니다.

이것이 「해결되지 않는」 유일한 이유는, 코드에 장해가 발생하고 있기 때문입니다.또, 이 에러 메세지가 표시되지 않는 이유는, 이 약속 체인이 최종적인 캐치로 종료되지 않기 때문입니다(어쨌든 표시되어 있는 한).

저는 당신의 사례에서 "기존의 사슬"을 제거하고 사슬을 캐치로 끊었습니다.이것은 당신에게 적합하지 않을 수도 있지만, 이것을 읽는 사람들은 항상 체인을 반환하거나 종료하는 것이 중요합니다.그렇지 않으면 잠재적인 오류, 심지어 코딩 오류도 숨겨집니다(여기서 발생한 것으로 추측됩니다).

Promise.all(state.routes.map(function(route) {
  return route.handler.promiseHandler().catch(function(err) {
    return err;
  });
}))
.then(function(arrayOfValuesOrErrors) {
  // handling of my array containing values and/or errors. 
})
.catch(function(err) {
  console.log(err.message); // some coding error in handling happened
});

새로운 답변

const results = await Promise.all(promises.map(p => p.catch(e => e)));
const validResults = results.filter(result => !(result instanceof Error));

Future Promise API

  • Chrome 76: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
  • 지금 바로 https://www.npmjs.com/package/promise.allsettled를 다운로드 받으실 수 있습니다.일부 브라우저에서는 allSettled가 브라우저 자체에 프리 인스톨 되어 있습니다.안심하고 패키지를 다운로드 할 수 있습니다.TypeScript에는 allSettled에 대한 기본 정의가 없습니다.

ES2020은 새로운 방법을 도입하고 있습니다.Promise " " ":Promise.allSettled().

Promise.allSettled입력 약속이 모두 해결되면 신호를 보냅니다. 즉, 약속은 이행되거나 거부됩니다.이것은 약속의 상태에 신경 쓰지 않고 성공 여부에 관계없이 작업이 언제 완료되었는지 알고 싶을 때 유용합니다.

(async function() {
  const promises = [
    fetch('//api.stackexchange.com/2.2'), // succeeds
    fetch('/this-will-fail') // fails
  ];

  const result = await Promise.allSettled(promises);
  console.log(result.map(promise => promise.status));
  // ['fulfilled', 'rejected']
})();

자세한 내용은 v8 블로그 투고를 참조하십시오.

Promise.all에도) 는 'Promise(약속)'라는 유틸리티 했습니다.executeAllPromises이 유틸리티 함수는 다음을 포함하는 개체를 반환합니다.results ★★★★★★★★★★★★★★★★★」errors.

이 '약속'에게 입니다.executeAllPromises항상 해결되는 새로운 약속으로 포장됩니다.약속하다첫 번째 스팟에는 해결값(있는 경우)이 유지되고 두 번째 스팟에는 오류가 유지됩니다(랩된 Promise가 거부된 경우).

로서, 「 」는executeAllPromises하여 최종 하고, "Resident"는 "Resident"의 합니다.results and の for for 。errors.

코드는 다음과 같습니다.

function executeAllPromises(promises) {
  // Wrap all Promises in a Promise that will always "resolve"
  var resolvingPromises = promises.map(function(promise) {
    return new Promise(function(resolve) {
      var payload = new Array(2);
      promise.then(function(result) {
          payload[0] = result;
        })
        .catch(function(error) {
          payload[1] = error;
        })
        .then(function() {
          /* 
           * The wrapped Promise returns an array:
           * The first position in the array holds the result (if any)
           * The second position in the array holds the error (if any)
           */
          resolve(payload);
        });
    });
  });

  var errors = [];
  var results = [];

  // Execute all wrapped Promises
  return Promise.all(resolvingPromises)
    .then(function(items) {
      items.forEach(function(payload) {
        if (payload[1]) {
          errors.push(payload[1]);
        } else {
          results.push(payload[0]);
        }
      });

      return {
        errors: errors,
        results: results
      };
    });
}

var myPromises = [
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject(new Error('3')),
  Promise.resolve(4),
  Promise.reject(new Error('5'))
];

executeAllPromises(myPromises).then(function(items) {
  // Result
  var errors = items.errors.map(function(error) {
    return error.message
  }).join(',');
  var results = items.results.join(',');
  
  console.log(`Executed all ${myPromises.length} Promises:`);
  console.log(`— ${items.results.length} Promises were successful: ${results}`);
  console.log(`— ${items.errors.length} Promises failed: ${errors}`);
});

약속.모두 정착했다

'Promise' 대신.모두 Promise를 사용합니다.결과에 관계없이 모든 약속이 성립되기를 기다리는 올세티드

let p1 = new Promise(resolve => resolve("result1"));
let p2 = new Promise( (resolve,reject) => reject('some troubles') );
let p3 = new Promise(resolve => resolve("result3"));

// It returns info about each promise status and value
Promise.allSettled([p1,p2,p3]).then(result=> console.log(result));

폴리필

if (!Promise.allSettled) {
  const rejectHandler = reason => ({ status: 'rejected', reason });
  const resolveHandler = value => ({ status: 'fulfilled', value });

  Promise.allSettled = function (promises) {
    const convertedPromises = promises
      .map(p => Promise.resolve(p).then(resolveHandler, rejectHandler));
    return Promise.all(convertedPromises);
  };
}

@jib가 말했듯이

Promise.all전부 아니면 아무것도 아니야.

허용되는'할 수 , '할 수 있다', '실패할 수 있다', '실패할 수 있다', '실패할 수 있다', '실패할 수 있다', '실패할 수 있다', '할 수 있다'로 넘어가겠습니다..then.

예를들면.

  Promise.all([
    doMustAsyncTask1,
    doMustAsyncTask2,
    doOptionalAsyncTask
    .catch(err => {
      if( /* err non-critical */) {
        return
      }
      // if critical then fail
      throw err
    })
  ])
  .then(([ mustRes1, mustRes2, optionalRes ]) => {
    // proceed to work with results
  })

비동기 대기 사용 -

여기에서는 비동기 함수 func1이 해결된 값을 반환하고 func2가 오류를 발생시켜 null을 반환하고 있습니다.이 경우 원하는 방법으로 처리하고 그에 따라 반환할 수 있습니다.

const callingFunction  = async () => {
    const manyPromises = await Promise.all([func1(), func2()]);
    console.log(manyPromises);
}


const func1 = async () => {
    return 'func1'
}

const func2 = async () => {
    try {
        let x;
        if (!x) throw "x value not present"
    } catch(err) {
       return null
    }
}

callingFunction();

출력은 - ['func1', null]

q 라이브러리 https://github.com/kriskowal/q을 사용할 경우 이 문제를 해결할 수 있는q.allSetled() 메서드가 있습니다.이 메서드는 풀파일 또는 거부 상태에 따라 모든 약속을 처리할 수 있습니다.

existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
  return route.handler.promiseHandler();
});
return q.allSettled(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
//so here you have all your promises the fulfilled and the rejected ones
// you can check the state of each promise
arrayResolved.forEach(function(item){
   if(item.state === 'fulfilled'){ // 'rejected' for rejected promises
     //do somthing
   } else {
     // do something else
   }
})
// do stuff with my array of resolved promises, eventually ending with a res.send();
});

ES8 를 사용하고 있는 유저는, 비동기 기능을 사용해 다음과 같은 조작을 실시할 수 있습니다.

var arrayOfPromises = state.routes.map(async function(route){
  try {
    return await route.handler.promiseHandler();
  } catch(e) {
    // Do something to handle the error.
    // Errored promises will return whatever you return here (undefined if you don't return anything).
  }
});

var resolvedPromises = await Promise.all(arrayOfPromises);

는 생각해 ?Promise.prototype.finally()

이것은 당신이 원하는 것을 할 수 있도록 설계되어 있는 것 같습니다.약속 중 일부가 거부되더라도 모든 약속이 해결되면(해결/거부) 기능을 실행합니다.

MDN 매뉴얼:

finally()그 결과에 관계없이 약속이 확정되면 처리나 정리를 하고 싶은 경우에 편리합니다.

finally() 방법은 '불러서'를 부르는 것과 ..then(onFinally, onFinally)단, 몇 가지 차이점이 있습니다.

함수를 인라인으로 작성할 때 강제로 두 번 선언하거나 해당 함수를 위한 변수를 만드는 대신 함수를 한 번 전달할 수 있습니다.

최종적으로 콜백은 어떠한 인수도 받지 않습니다.약속이 이행되었는지 거부되었는지 신뢰할 수 있는 방법이 없기 때문입니다.이 사용 사례는 거절 이유 또는 이행 가치에 관심이 없기 때문에 제공할 필요가 없는 경우에 적합합니다.

★★★★★★★★★★★★★★★와 달리Promise.resolve(2).then(() => {}, () => {})됩니다), (미정의로 해결됩니다), (미정의로 해결됩니다),Promise.resolve(2).finally(() => {})2로 하겠습니다.마찬가지로 similarly similarly similarly similarly similarly와는 Promise.reject(3).then(() => {}, () => {})정의되지 않은 됩니다), (미정의로 이행됩니다), (미정의로 이행됩니다),Promise.reject(3).finally(() => {})3으로 됩니다.

== 예비 ==

JavaScript를 지원하지 않는 Promise.prototype.finally()다음 회피책은 Jake Archibald에서 사용할 수 있습니다.Promise.all(promises.map(p => p.catch(() => undefined)));

레벨에서 를 할 수 배열에 는 """가 .undefined필요에 따라 처리하여 나머지 결과를 사용할 수 있습니다.

여기에서는 첫 번째 약속을 거부했기 때문에 정의되지 않은 것으로 나타나지만 두 번째 약속의 결과인 인덱스 1을 사용할 수 있습니다.

const manyPromises = Promise.all([func1(), func2()]).then(result => {
    console.log(result[0]);  // undefined
    console.log(result[1]);  // func2
});

function func1() {
    return new Promise( (res, rej) => rej('func1')).catch(err => {
        console.log('error handled', err);
    });
}

function func2() {
    return new Promise( (res, rej) => setTimeout(() => res('func2'), 500) );
}

약속.필터로 모두 정리됨

const promises = [
  fetch('/api-call-1'),
  fetch('/api-call-2'),
  fetch('/api-call-3'),
];
// Imagine some of these requests fail, and some succeed.

const resultFilter = (result, error) => result.filter(i => i.status === (!error ? 'fulfilled' : 'rejected')).map(i => (!error ? i.value : i.reason));

const result = await Promise.allSettled(promises);

const fulfilled = resultFilter(result); // all fulfilled results
const rejected = resultFilter(result, true); // all rejected results
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
let sum = 0;
let promiseErrorArr = [];

Promise.allSettled(promises)
.then((results) => {
          results.forEach(result => {
            if (result.status === "rejected") {
              sum += 1;
              promiseErrorArr.push(result)
            }
          })
    return ( (sum>0) ? promiseFailed() : promisePassed())
})

function promiseFailed(){
  console.log('one or all failed!')
  console.log(promiseErrorArr)
}

function promisePassed(){
  console.log('all passed!')
}

// expected output:
// "one or all failed!"
// Array [Object { status: "rejected", reason: "foo" }]

또는 하나의 실패가 있을 때 해결된 약속의 가치를 특별히 신경 쓰지 않고 계속 실행하기를 원하는 경우 다음과 같은 작업을 수행할 수 있습니다. 이러한 작업은 모두 성공했을 때 정상적으로 해결되고 실패한 약속 중 하나가 실패했을 때 거부됩니다.

function promiseNoReallyAll (promises) {
  return new Promise(
    async (resolve, reject) => {
      const failedPromises = []

      const successfulPromises = await Promise.all(
        promises.map(
          promise => promise.catch(error => {
            failedPromises.push(error)
          })
        )
      )

      if (failedPromises.length) {
        reject(failedPromises)
      } else {
        resolve(successfulPromises)
      }
    }
  )
}

약속을 반환하는 함수는 항상 오류를 포착하고 합의된 값(예: error.message)을 반환하는 방식으로 포장할 수 있습니다.그러면 예외가 약속까지 확대되지는 않습니다.모든 기능을 무효로 합니다.

async function resetCache(ip) {

    try {

        const response = await axios.get(`http://${ip}/resetcache`);
        return response;

    }catch (e) {

        return {status: 'failure', reason: 'e.message'};
    }

}

동기화하지 않고 이 작업을 수행할 수 있는 방법을 찾았습니다.

Promise.all아무것도 아니다.

그러니... 동봉된 약속을 이용해서 결의를 강요하는 겁니다


      let safePromises = originalPrmises.map((imageObject) => {
            return new Promise((resolve) => {
              // Do something error friendly
              promise.then(_res => resolve(res)).catch(_err => resolve(err))
            })
        })
    })

    // safe
    return Promise.all(safePromises)

결과에서 오류를 식별하는 방법을 알아야 합니다.표준 예상 오류가 없는 경우 결과에서 식별할 수 있도록 캐치 블록의 각 오류에 대해 변환을 실행하는 것이 좋습니다.

try {
  let resArray = await Promise.all(
    state.routes.map(route => route.handler.promiseHandler().catch(e => e))
  );

  // in catch(e => e) you can transform your error to a type or object
  // that makes it easier for you to identify whats an error in resArray
  // e.g. if you expect your err objects to have e.type, you can filter
  // all errors in the array eg
  // let errResponse = resArray.filter(d => d && d.type === '<expected type>')
  // let notNullResponse = resArray.filter(d => d)

  } catch (err) {
    // code related errors
  }

에러 로그를 작성하는 최선의 방법은 아니지만, 약속의 모든 것을 항상 어레이로 설정할 수 있습니다.모두 및 결과 결과를 새 변수에 저장합니다.

graphQL을 사용하는 경우, 어떠한 경우에도 응답을 후처리해야 하며, 올바른 참조를 찾지 못하면 앱이 크래쉬하여 문제가 있는 위치를 좁힙니다.

const results = await Promise.all([
  this.props.client.query({
    query: GET_SPECIAL_DATES,
  }),
  this.props.client.query({
    query: GET_SPECIAL_DATE_TYPES,
  }),
  this.props.client.query({
    query: GET_ORDER_DATES,
  }),
]).catch(e=>console.log(e,"error"));
const specialDates = results[0].data.specialDates;
const specialDateTypes = results[1].data.specialDateTypes;
const orderDates = results[2].data.orders;

해서Promise.all동작하도록 설계되어 있습니다.reject()그럼 메서드 전체가 즉시 실패합니다.

로는 '사용하다'가 할 수 .Promise.all하려면 , 「어느 것」을 하지 말아 .reject()당신의 약속에 진술할 수 있습니다.단, 하나의 기본 약속이 응답을 받지 못할 경우에 대비하여 앱/스크립트가 정지되지 않도록 하려면 타임아웃을 설정해야 합니다.

function getThing(uid,branch){
    return new Promise(function (resolve, reject) {
        xhr.get().then(function(res) {
            if (res) {
                resolve(res);
            } 
            else {
                resolve(null);
            }
            setTimeout(function(){reject('timeout')},10000)
        }).catch(function(error) {
            resolve(null);
        });
    });
}

나는 이 문제를 더 아름답게 다루기 위해 npm 도서관을 썼다.https://github.com/wenshin/promiseallend

설치하다

npm i --save promiseallend

2017-02-25 새로운 api, 약속을 깨는 원칙이 아닙니다.

const promiseAllEnd = require('promiseallend');

const promises = [Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)];
const promisesObj = {k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)};

// input promises with array
promiseAllEnd(promises, {
    unhandledRejection(error, index) {
        // error is the original error which is 'error'.
        // index is the index of array, it's a number.
        console.log(error, index);
    }
})
    // will call, data is `[1, undefined, 2]`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// input promises with object
promiseAllEnd(promisesObj, {
    unhandledRejection(error, prop) {
        // error is the original error.
        // key is the property of object.
        console.log(error, prop);
    }
})
    // will call, data is `{k1: 1, k3: 2}`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// the same to `Promise.all`
promiseAllEnd(promises, {requireConfig: true})
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [false, true, false]})
    // won't call
    .then(data => console.log(data))
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [true, false, false]})
    // will call, data is `[1, undefined, 2]`.
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

————————————————————————————————

오래된 나쁜 api, 사용하지 마세요!

let promiseAllEnd = require('promiseallend');

// input promises with array
promiseAllEnd([Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)])
    .then(data => console.log(data)) // [1, undefined, 2]
    .catch(error => console.log(error.errorsByKey)) // {1: 'error'}

// input promises with object
promiseAllEnd({k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)})
    .then(data => console.log(data)) // {k1: 1, k3: 2}
    .catch(error => console.log(error.errorsByKey)) // {k2: 'error'}

언급URL : https://stackoverflow.com/questions/30362733/handling-errors-in-promise-all

반응형