Xử lý lỗi trong Promise.all


266

Tôi có một loạt các Lời hứa mà tôi đang giải quyết Promise.all(arrayOfPromises);

Tôi tiếp tục chuỗi tiếp tục hứa hẹn. Trông giống như thế này

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();
});

Tôi muốn thêm một câu lệnh bắt để xử lý một lời hứa riêng lẻ trong trường hợp nó bị lỗi, nhưng khi tôi thử, Promise.allsẽ trả về lỗi đầu tiên mà nó tìm thấy (bỏ qua phần còn lại), và sau đó tôi không thể lấy dữ liệu từ phần còn lại của các lời hứa trong mảng (không có lỗi).

Tôi đã thử làm một cái gì đó như ..

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();
});

Nhưng điều đó không giải quyết.

Cảm ơn!

-

Biên tập:

Những gì các câu trả lời dưới đây đã nói là hoàn toàn đúng, mã bị phá vỡ do các lý do khác. Trong trường hợp bất cứ ai quan tâm, đây là giải pháp tôi đã kết thúc với ...

Chuỗi máy chủ Node Express

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;
            })
    };

Cuộc gọi API (cuộc gọi route.async)

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

Đặt .catchfor Promise.alltrước .thendường như đã phục vụ mục đích bắt bất kỳ lỗi nào từ các lời hứa ban đầu, nhưng sau đó trả lại toàn bộ mảng cho tiếp theo.then

Cảm ơn!


2
Nỗ lực của bạn có vẻ như sẽ hoạt động được. Có lẽ sau này lại có vấn đề khác?
Ry-

.then(function(data) { return data; })có thể được bỏ qua hoàn toàn
Bergi

Lý do duy nhất mà những điều trên không nên giải quyết là nếu bạn không hiển thị cho chúng tôi tất cả mã trong trình xử lý thenhoặc catchcó lỗi bị ném vào bên trong. Nhân tiện, đây là nút?

1
Bạn không có kết quả cuối cùng trong "chuỗi hiện tại" của mình, vì vậy có thể có những lỗi bạn không thấy có thể giải thích tại sao nó "không giải quyết". Hãy thử thêm nó và xem những gì bạn nhận được lỗi.
jib

đây là câu trả lời: stackoverflow.com/questions/31424561/
Kẻ

Câu trả lời:


189

Promise.alllà tất cả hoặc không có gì. Nó giải quyết một khi tất cả các lời hứa trong mảng giải quyết hoặc từ chối ngay khi một trong số chúng từ chối. Nói cách khác, nó sẽ giải quyết với một mảng gồm tất cả các giá trị được giải quyết hoặc từ chối với một lỗi duy nhất.

Một số thư viện có một cái gì đó được gọi Promise.when, mà tôi hiểu thay vì chờ đợi tất cả các lời hứa trong mảng sẽ giải quyết hoặc từ chối, nhưng tôi không quen với nó và nó không có trong ES6.

Ma cua ban

Tôi đồng ý với những người khác ở đây rằng sửa chữa của bạn nên làm việc. Nó sẽ giải quyết với một mảng có thể chứa hỗn hợp các giá trị thành công và các đối tượng lỗi. Thật bất thường khi vượt qua các đối tượng lỗi trong đường dẫn thành công nhưng giả sử mã của bạn đang mong đợi chúng, tôi thấy không có vấn đề gì với nó.

Lý do duy nhất tôi có thể nghĩ về lý do tại sao nó "không giải quyết" là do lỗi mã không hiển thị cho chúng tôi và lý do bạn không thấy bất kỳ thông báo lỗi nào về việc này là vì chuỗi hứa hẹn này không bị chấm dứt với trận chung kết bắt (theo như những gì bạn đang chỉ cho chúng tôi).

Tôi đã lấy tự do bao thanh toán "chuỗi hiện tại" từ ví dụ của bạn và chấm dứt chuỗi bằng cách nắm bắt. Điều này có thể không phù hợp với bạn, nhưng đối với những người đọc nó, điều quan trọng là luôn luôn trả lại hoặc chấm dứt chuỗi, hoặc lỗi tiềm ẩn, thậm chí lỗi mã hóa, sẽ bị ẩn (đó là điều tôi nghi ngờ đã xảy ra ở đây):

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
});

4
Bạn (và các ý kiến ​​trên) đã đúng. Route.handler.promiseHandler của tôi cần đến .catch () và trả về lỗi. Tôi cũng cần thêm .catch () cuối cùng vào cuối chuỗi. Cảm ơn đã chuyển tiếp tầm quan trọng của việc xử lý thành công / lỗi ở mỗi bước của chuỗi :).
Jon

2
Tôi cũng phát hiện ra rằng nếu tôi ném lỗi trong .catch () của mình cho route.handler.promiseHandler, nó sẽ tự động đi đến lần bắt cuối cùng. Nếu tôi trả lại lỗi thay vào đó, nó sẽ làm những gì tôi muốn và xử lý toàn bộ mảng.
Jon

2
Bây giờ có một phương pháp tiêu chuẩn Promise.allSettled()với sự hỗ trợ tốt. Xem tài liệu tham khảo .
Andréa Maugars

Có, Promise.allthất bại, khi chủ đề đầu tiên thất bại. Nhưng thật không may, tất cả các chủ đề khác vẫn tiếp tục chạy cho đến khi họ hoàn thành. Không có gì bị hủy, thậm chí tệ hơn: Không có cách nào để hủy một chủ đề Promise. Vì vậy, bất cứ điều gì các luồng đang làm (và thao tác) chúng tiếp tục, chúng thay đổi trạng thái và biến, chúng sử dụng CPU, nhưng cuối cùng chúng không trả về kết quả của chúng. Bạn cần lưu ý điều này để không tạo ra sự hỗn loạn, ví dụ như khi bạn lặp lại / thử lại cuộc gọi.
Marc Wäckerlin

143

TRẢ LỜI MỚI

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

API hứa hẹn TƯƠNG LAI


11
Mặc dù ekhông phải là một Error. Nó có thể là một chuỗi, ví dụ, nếu ai đó trả lại nó như thế nào Promise.reject('Service not available').
Klesun

@ArturKlesun làm thế nào chúng ta có thể phân loại lời hứa nào dẫn đến lỗi và điều nào không?
Shubham Jain

5
@ shubham-jain với .then().catch(). Promise.resolve()sẽ truyền giá trị cho cái trước, trong khi Promise.reject()sẽ chuyển nó cho cái sau. Bạn có thể bọc chúng trong đối tượng chẳng hạn : p.then(v => ({success: true, value: v})).catch(e => ({success: false, error: e})).
Klesun

2
Tại sao bạn sẽ lọc kết quả? Điều đó sẽ vô nghĩa nếu bạn đang làm bất cứ điều gì với kết quả - bạn cần thứ tự để biết giá trị trả về là từ lời hứa nào!
Ryan Taylor

21

Để tiếp tục Promise.allvòng lặp (ngay cả khi Promise từ chối) tôi đã viết một hàm tiện ích được gọi executeAllPromises. Hàm tiện ích này trả về một đối tượng với resultserrors.

Ý tưởng là tất cả những Lời hứa mà bạn vượt qua executeAllPromisessẽ được gói gọn trong một Lời hứa mới sẽ luôn giải quyết. Promise mới giải quyết với một mảng có 2 điểm. Vị trí đầu tiên giữ giá trị giải quyết (nếu có) và vị trí thứ hai giữ lỗi (nếu Promise được bao bọc từ chối).

Bước cuối cùng, executeAllPromisestích lũy tất cả các giá trị của các lời hứa được bọc và trả về đối tượng cuối cùng với một mảng cho resultsvà một mảng cho errors.

Đây là mã:

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}`);
});


2
Điều này có thể được thực hiện đơn giản hơn. Xem stackoverflow.com/a/36115549/918910
jib

18

ES2020 giới thiệu phương thức mới cho loại Promise: Promise.allSettled()
Promise.allSettled cung cấp cho bạn một tín hiệu khi tất cả các lời hứa đầu vào được giải quyết, có nghĩa là chúng được thực hiện hoặc bị từ chối. Điều này rất hữu ích trong trường hợp bạn không quan tâm đến trạng thái của lời hứa, bạn chỉ muốn biết khi nào công việc được thực hiện, bất kể nó có thành công hay không.

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

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

Đọc thêm trong bài đăng trên blog v8 https://v8.dev/features/promise-combinators


13

Như @jib đã nói,

Promise.all là tất cả hoặc không có gì.

Mặc dù vậy, bạn có thể kiểm soát một số lời hứa "được phép" thất bại và chúng tôi muốn tiến hành .then.

Ví dụ.

  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
  })

6

nếu bạn có thể sử dụng thư viện q https://github.com/kriskowal/q thì nó có phương thức q.allSettled () có thể giải quyết vấn đề này, bạn có thể xử lý mọi lời hứa tùy thuộc vào trạng thái của nó đầy đủ hoặc bị từ chối

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();
});

Vì bạn đang đề xuất sử dụng một số thư viện ( q), sẽ hữu ích hơn nếu bạn cung cấp một ví dụ sử dụng liên quan đến câu hỏi. Vì thế, câu trả lời của bạn không giải thích cách thư viện này có thể giúp giải quyết vấn đề.
ishmaelMakitla

đã thêm một ví dụ như được đề xuất
Mohamed Mahmoud

1
Circa 2018 người ta phải luôn luôn thấy những gì Sindre có sẵn :-). github.com/sindresorhus/p-seling . Với các mô-đun mục đích duy nhất của Sindre, bạn không phải nhập một thư viện lớn như q chỉ một bit.
DKebler

6

Sử dụng Async đang chờ -

ở đây, một hàm async func1 đang trả về giá trị đã giải quyết và func2 đang đưa ra lỗi và trả về null trong tình huống này, chúng ta có thể xử lý nó theo cách chúng ta muốn và trả về.

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();

Đầu ra là - ['func1', null]


4

Đối với những người sử dụng ES8 vấp ngã ở đây, bạn có thể thực hiện một số thao tác như sau, sử dụng các hàm async :

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);

3

Chúng tôi có thể xử lý từ chối ở cấp độ hứa hẹn riêng lẻ, vì vậy khi chúng tôi nhận được kết quả trong mảng kết quả của mình, chỉ số mảng đã bị từ chối sẽ là undefined. Chúng tôi có thể xử lý tình huống đó khi cần và sử dụng các kết quả còn lại.

Ở đây tôi đã từ chối lời hứa đầu tiên, vì vậy nó không được xác định, nhưng chúng ta có thể sử dụng kết quả của lời hứa thứ hai, ở chỉ số 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) );
}


Làm thế nào bạn có thể làm một điều tương tự nếu chúng tôi sử dụng async đang chờ?
Rudresh Ajgaonkar

Tôi đã trả lời câu hỏi của bạn, xin vui lòng tìm liên kết cho câu trả lời. stackoverflow.com/a/55216763/4079716
Naya Patel

2

Bạn đã xem xét Promise.prototype.finally()chưa?

Nó dường như được thiết kế để thực hiện chính xác những gì bạn muốn - thực hiện một chức năng một khi tất cả các lời hứa đã được giải quyết (giải quyết / từ chối), bất kể một số lời hứa bị từ chối.

Từ tài liệu MDN :

Các finally()phương pháp có thể hữu ích nếu bạn muốn làm một số chế biến hoặc dọn dẹp một lần lời hứa được giải quyết, bất kể kết quả của nó.

Các finally()phương pháp này rất giống với gọi .then(onFinally, onFinally)tuy nhiên có vài điểm khác biệt:

Khi tạo một hàm nội tuyến, bạn có thể chuyển nó một lần, thay vì buộc phải khai báo hai lần hoặc tạo một biến cho nó.

Một cuộc gọi lại cuối cùng sẽ không nhận được bất kỳ đối số nào, vì không có phương tiện đáng tin cậy nào để xác định xem lời hứa đã được thực hiện hay từ chối. Trường hợp sử dụng này là chính xác khi bạn không quan tâm đến lý do từ chối hoặc giá trị thực hiện và do đó không cần phải cung cấp nó.

Không giống như Promise.resolve(2).then(() => {}, () => {})(sẽ được giải quyết với không xác định), Promise.resolve(2).finally(() => {})sẽ được giải quyết bằng 2. Tương tự, không giống như Promise.reject(3).then(() => {}, () => {})(sẽ được hoàn thành với không xác định), Promise.reject(3).finally(() => {})sẽ bị từ chối với 3.

== Dự phòng ==

Nếu phiên bản JavaScript của bạn không hỗ trợ, Promise.prototype.finally()bạn có thể sử dụng cách giải quyết này từ Jake Archibald :Promise.all(promises.map(p => p.catch(() => undefined)));


1
Có, cho đến khi Promises.allSettled()thực sự được triển khai (được MDN ghi lại ở đây ), thì Promises.all.finally()dường như sẽ hoàn thành điều tương tự. Tôi chuẩn bị thử ...
kẹt

@jamess Tại sao bạn không đưa ra nhận xét này như một câu trả lời thích hợp? Không có câu trả lời nào đề cập đến ES6 allSettled().
khen ngợi

@pravin - Từ những gì tôi có thể nói, allSettled()chưa được triển khai ở bất kỳ đâu (vì vậy), vì vậy tôi không muốn đi trước thực tế. Tôi đã thành công với Promises.all(myPromiseArray).finally(), và điều đó phù hợp với câu trả lời này. Khi allSettled()thực sự tồn tại, sau đó tôi có thể kiểm tra nó và tìm hiểu làm thế nào nó thực sự hoạt động. Cho đến lúc đó, ai biết những gì trình duyệt sẽ thực sự thực hiện? Trừ khi bạn có thông tin gần đây ngược lại ...
kẹt

@jamess Đúng là nó vẫn đang trong giai đoạn phác thảo .. tuy nhiên FF và chrome mới nhất dường như hỗ trợ đầy đủ .. Không chắc chắn về tính ổn định của nó .. Mozilla Docs Dù sao điểm tôi đang cố gắng thực hiện là nó sẽ dễ tìm hơn nhiều nếu đó là một câu trả lời hơn là một bình luận .. thì bạn vẫn gọi :)
khen ngợi

@pravin - Tại thời điểm tôi đăng bình luận của mình, nó không được thực hiện ở bất cứ đâu. Tôi mới thử nghiệm trên Firefox và Chrome: Promise.allSettledkhông được triển khai trong Firefox, nhưng dường như nó tồn tại trong Chrome. Chỉ vì các tài liệu nói rằng nó được thực hiện không có nghĩa là nó thực sự được thực hiện. Tôi sẽ không sử dụng nó bất cứ lúc nào sớm.
kẹt

0

Cách khác, nếu bạn gặp trường hợp bạn không đặc biệt quan tâm đến các giá trị của những lời hứa đã giải quyết khi có một thất bại nhưng bạn vẫn muốn chúng chạy, bạn có thể làm điều gì đó như thế này sẽ giải quyết với những lời hứa như bình thường khi tất cả họ đều thành công và từ chối với những lời hứa thất bại khi bất kỳ ai trong số họ thất bại:

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)
      }
    }
  )
}

0

Bạn luôn có thể gói các hàm trả lại lời hứa của mình theo cách chúng bắt lỗi và trả về thay vào đó là một giá trị đã thỏa thuận (ví dụ: error.message), vì vậy ngoại lệ sẽ không chuyển sang hàm Promise.all và vô hiệu hóa nó.

async function resetCache(ip) {

    try {

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

    }catch (e) {

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

}

0

Tôi đã tìm thấy một cách (cách giải quyết) để làm điều này mà không làm cho nó đồng bộ hóa.

Vì vậy, như nó đã được đề cập trước đây Promise.alllà tất cả không có.

vì vậy ... Sử dụng một lời hứa kèm theo để bắt và buộc giải quyết.


      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)

0

Bạn sẽ cần biết cách xác định lỗi trong kết quả của mình. Nếu bạn không có lỗi dự kiến ​​tiêu chuẩn, tôi khuyên bạn nên chạy một biến đổi trên từng lỗi trong khối bắt khiến nó có thể nhận dạng được trong kết quả của bạn.

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
  }

0

Không phải là cách tốt nhất để ghi nhật ký lỗi, nhưng bạn luôn có thể đặt mọi thứ thành một mảng cho lời hứa ALL và lưu kết quả kết quả vào các biến mới.

Nếu bạn sử dụng graphQL, bạn cần xử lý phản hồi bất kể và nếu không tìm thấy tham chiếu chính xác, nó sẽ làm sập ứng dụng, thu hẹp nơi xảy ra sự cố

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;

-1

Đó là cách Promise.allthiết kế để làm việc. Nếu một lời hứa duy nhất reject(), toàn bộ phương pháp ngay lập tức thất bại.

Có những trường hợp sử dụng mà người ta có thể muốn Promise.allcho phép những lời hứa thất bại. Để thực hiện điều này, chỉ cần không sử dụng bất kỳ reject()tuyên bố nào trong lời hứa của bạn. Tuy nhiên, để đảm bảo ứng dụng / tập lệnh của bạn không bị đóng băng trong trường hợp bất kỳ lời hứa cơ bản nào không bao giờ nhận được phản hồi, bạn cần đặt thời gian chờ cho nó.

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);
        });
    });
}

đây là câu trả lời: stackoverflow.com/questions/31424561/
Kẻ

Không sử dụng reject()trong lời hứa của bạn là tốt, nhưng nếu bạn cần sử dụng lời hứa của thư viện khác thì sao?
Dan Dascalescu

-8

Tôi đã viết một thư viện npm để giải quyết vấn đề này đẹp hơn. https://github.com/wenshin/promiseallend

Tải về

npm i --save promiseallend

2017 / 02-25 api mới, nó không phá vỡ các nguyên tắc hứa hẹn

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))

Giữa chúng tôi và tình yêu

Api cũ xấu, không sử dụng nó!

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'}

Làm thế nào nó hoạt động? Vui lòng hiển thị và giải thích việc thực hiện chức năng của bạn.
Bergi

Tôi đã viết một logic đồng thời mới như thế Promise.all. Nhưng nó sẽ thu thập tất cả dữ liệu và lỗi của mọi lời hứa. Ngoài ra, nó hỗ trợ đầu vào đối tượng, nó không phải là điểm. sau khi thu thập tất cả dữ liệu và lỗi, tôi ghi đè promise.thenphương thức để xử lý các cuộc gọi lại đã đăng ký bao gồm bị từ chối và hoàn thành. Để biết chi tiết, bạn có thể xem
wenshin

Uh, mã đó sẽ gọi cả hai onFulfilledonRejectedtrình xử lý được chuyển đến then?
Bergi

Có, chỉ khi tình trạng lời hứa trộn lẫn fulfilledrejected. Nhưng thực sự nó gây ra một vấn đề khó tương thích với tất cả các trường hợp sử dụng lời hứa thông thường, như onFulfilledonRejectedtất cả trả lại Promise.reject()hoặc Promise.resolve(). Cho đến nay tôi không rõ làm thế nào để giải quyết nó, có ai có ý tưởng tốt hơn không? Câu trả lời tốt nhất hiện nay có một vấn đề là, nó có thể không thể lọc dữ liệu và lỗi trong môi trường trình duyệt.
wenshin

Chúng ta có cần cài đặt mô-đun npm với trình quản lý gói pip python không?
sevenfourk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.