Menangani kesalahan di Promise.all

267

Saya memiliki berbagai Janji yang saya selesaikan Promise.all(arrayOfPromises);

Saya melanjutkan untuk melanjutkan rantai janji. Terlihat seperti ini

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

Saya ingin menambahkan pernyataan tangkap untuk menangani janji individu jika terjadi kesalahan, tetapi ketika saya mencoba, Promise.allmengembalikan kesalahan pertama yang ditemukan (mengabaikan sisanya), dan kemudian saya tidak bisa mendapatkan data dari sisa janji di array (itu tidak salah).

Saya sudah mencoba melakukan sesuatu seperti ..

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

Tetapi itu tidak menyelesaikan.

Terima kasih!

-

Edit:

Apa jawaban di bawah ini sepenuhnya benar, kode itu rusak karena alasan lain. Jika ada yang tertarik, ini adalah solusi yang saya akhirnya ...

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

Panggilan API (panggilan route.async)

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

Menempatkan .catchuntuk Promise.allsebelum .thentampaknya telah melayani tujuan menangkap kesalahan dari janji asli, tetapi kemudian mengembalikan seluruh array ke yang berikutnya.then

Terima kasih!

Jon
sumber
2
Upaya Anda sepertinya berhasil ... mungkin ada masalah lain di suatu tempat nanti?
Ry-
.then(function(data) { return data; })dapat sepenuhnya dihapus
Bergi
Satu-satunya alasan bahwa hal di atas tidak dapat diselesaikan adalah jika Anda tidak menunjukkan kepada kami semua kode di thenatau catchpenangan dan ada kesalahan yang terjadi. Omong-omong, apakah simpul ini?
1
Anda tidak memiliki hasil akhir dalam "rantai yang ada", jadi mungkin ada kesalahan yang tidak Anda lihat yang mungkin menjelaskan mengapa itu "tidak menyelesaikan". Coba tambahkan itu dan lihat kesalahan apa yang Anda dapatkan.
jib
inilah jawabannya: stackoverflow.com/questions/31424561/…
Humoyun Ahmad

Jawaban:

190

Promise.allsemua atau tidak sama sekali. Itu menyelesaikan setelah semua janji dalam array menyelesaikan, atau menolak segera setelah salah satu dari mereka menolak. Dengan kata lain, itu bisa diselesaikan dengan array dari semua nilai yang diselesaikan, atau ditolak dengan satu kesalahan.

Beberapa perpustakaan memiliki sesuatu yang disebut Promise.when, yang saya pahami sebagai gantinya akan menunggu semua janji dalam array untuk menyelesaikan atau menolak, tapi saya tidak terbiasa dengan itu, dan itu tidak di ES6.

Kode Anda

Saya setuju dengan orang lain di sini bahwa perbaikan Anda harus bekerja. Itu harus diselesaikan dengan array yang mungkin berisi campuran dari nilai yang berhasil dan objek kesalahan. Itu tidak biasa untuk melewatkan objek kesalahan di jalur sukses tetapi dengan asumsi kode Anda mengharapkan mereka, saya tidak melihat masalah dengan itu.

Satu-satunya alasan saya bisa memikirkan mengapa itu "tidak menyelesaikan" adalah karena kode gagal Anda tidak menunjukkan kepada kami dan alasan Anda tidak melihat pesan kesalahan tentang ini adalah karena rantai janji ini tidak diakhiri dengan final catch (sejauh apa yang Anda tunjukkan pada kami).

Saya telah mengambil kebebasan untuk memfaktorkan "rantai yang ada" dari contoh Anda dan mengakhiri rantai dengan tangkapan. Ini mungkin tidak tepat untuk Anda, tetapi bagi orang yang membaca ini, penting untuk selalu mengembalikan atau menghentikan rantai, atau potensi kesalahan, bahkan kesalahan pengodean, akan disembunyikan (yang saya duga terjadi di sini):

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
});
jib
sumber
4
Anda (dan komentar di atas) benar. Route.handler.promiseHandler saya perlu .catch () dan mengembalikan kesalahan. Saya juga perlu menambahkan .catch () terakhir ke akhir rantai. Terima kasih telah menyampaikan pentingnya memiliki penangan keberhasilan / kesalahan di setiap langkah rantai :).
Jon
2
Saya menemukan juga bahwa jika saya melempar kesalahan dalam .catch () saya untuk route.handler.promiseHandler, itu akan secara otomatis menuju tangkapan akhir. Jika saya mengembalikan kesalahan, itu akan melakukan apa yang saya inginkan dan menangani seluruh array.
Jon
2
Sekarang ada metode standar Promise.allSettled()dengan dukungan yang layak. Lihat referensi .
Andréa Maugars
Ya, Promise.allgagal, saat utas pertama gagal. Namun sayangnya semua utas lainnya masih terus berjalan sampai selesai. Tidak ada yang dibatalkan, bahkan lebih buruk: Tidak ada cara untuk membatalkan utas Promise. Jadi, apa pun yang dilakukan thread (dan memanipulasi) mereka melanjutkan, mereka mengubah status dan variabel, mereka menggunakan CPU, tetapi pada akhirnya mereka tidak mengembalikan hasilnya. Anda perlu menyadari hal ini untuk tidak menghasilkan kekacauan, misalnya ketika Anda mengulangi / coba lagi panggilan.
Marc Wäckerlin
144

JAWABAN BARU

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

API Janji MASA DEPAN

Solominh
sumber
11
Padahal etidak harus menjadi seorang Error. Ini bisa berupa string, misalnya, jika seseorang mengembalikannya seperti Promise.reject('Service not available').
Klesun
@ ArturKlesun bagaimana kita bisa mengklasifikasikan janji mana yang menghasilkan kesalahan dan mana yang tidak?
Shubham Jain
5
@ shubham-jain dengan .then()dan .catch(). Promise.resolve()akan memberikan nilai ke yang pertama, sedangkan Promise.reject()akan memberikannya ke yang kedua. Anda dapat membungkus mereka dalam objek misalnya: p.then(v => ({success: true, value: v})).catch(e => ({success: false, error: e})).
Klesun
2
Mengapa Anda menyaring hasilnya? Itu tidak masuk akal jika Anda melakukan sesuatu dengan hasilnya - Anda perlu mengetahui nilai yang dikembalikan dari janji yang mana!
Ryan Taylor
21

Untuk melanjutkan Promise.allloop (bahkan ketika Janji menolak) saya menulis fungsi utilitas yang disebut executeAllPromises. Fungsi utilitas ini mengembalikan objek dengan resultsdan errors.

Idenya adalah bahwa semua Janji yang Anda lewati executeAllPromisesakan dibungkus menjadi Janji baru yang akan selalu diselesaikan. Janji baru diselesaikan dengan array yang memiliki 2 tempat. Spot pertama memiliki nilai penyelesaian (jika ada) dan spot kedua menyimpan kesalahan (jika Janji yang dibungkus menolak).

Sebagai langkah terakhir, executeAllPromisesakumulasi semua nilai janji yang dibungkus dan mengembalikan objek akhir dengan array untuk resultsdan array untuk errors.

Ini kodenya:

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

Benny Neugebauer
sumber
2
Ini bisa dilakukan dengan lebih sederhana. Lihat stackoverflow.com/a/36115549/918910
jib
18

ES2020 memperkenalkan metode baru untuk tipe Janji: Promise.allSettled()
Promise.allSettled memberi Anda sinyal ketika semua janji input diselesaikan, yang berarti mereka dipenuhi atau ditolak. Ini berguna dalam kasus di mana Anda tidak peduli dengan keadaan janji, Anda hanya ingin tahu kapan pekerjaan itu dilakukan, terlepas dari apakah itu berhasil.

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

Baca lebih lanjut di posting blog v8 https://v8.dev/features/promise-combinators

MosheZada
sumber
13

Seperti yang dikatakan @jib,

Promise.all semua atau tidak sama sekali.

Meskipun demikian, Anda dapat mengontrol janji-janji tertentu yang "diizinkan" untuk gagal dan kami ingin melanjutkannya .then.

Sebagai contoh.

  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
  })
Herman
sumber
6

jika Anda bisa menggunakan perpustakaan q https://github.com/kriskowal/q ia memiliki metode q.allSettled () yang dapat menyelesaikan masalah ini, Anda dapat menangani setiap janji tergantung pada negaranya apakah terpenuhi atau ditolak sehingga

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();
});
Mohamed Mahmoud
sumber
Karena Anda menyarankan penggunaan beberapa perpustakaan ( q), akan lebih bermanfaat jika Anda memberikan contoh penggunaan yang terkait dengan pertanyaan. Seperti berdiri, jawaban Anda tidak menjelaskan bagaimana perpustakaan ini dapat membantu menyelesaikan masalah.
ishmaelMakitla
menambahkan contoh seperti yang disarankan
Mohamed Mahmoud
1
Sekitar tahun 2018 kita harus selalu melihat apa yang tersedia di Sindre :-). github.com/sindresorhus/p-settle . Dengan modul tujuan tunggal Sindre Anda tidak perlu mengimpor perpustakaan besar seperti q hanya satu bit.
DKebler
6

Menggunakan Async, tunggu -

di sini satu fungsi async func1 mengembalikan nilai yang diselesaikan, dan func2 melempar kesalahan dan mengembalikan nol dalam situasi ini, kita bisa menanganinya seperti yang kita inginkan dan mengembalikan sesuai.

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

Output adalah - ['func1', null]

Nayan Patel
sumber
4

Bagi mereka yang menggunakan ES8 yang tersandung di sini, Anda dapat melakukan sesuatu seperti berikut, menggunakan fungsi 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);
Tyler Yasaka
sumber
3

Kami dapat menangani penolakan di tingkat janji individual, jadi ketika kami mendapatkan hasil di larik hasil kami, indeks larik yang telah ditolak akan menjadi undefined. Kami dapat menangani situasi itu sesuai kebutuhan, dan menggunakan hasil yang tersisa.

Di sini saya telah menolak janji pertama, jadi janji itu tidak ditentukan, tetapi kita bisa menggunakan hasil dari janji kedua, yaitu pada indeks 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) );
}

Nayan Patel
sumber
Bagaimana Anda bisa melakukan hal serupa jika kita menggunakan async?
Rudresh Ajgaonkar
Saya telah menjawab pertanyaan Anda, silakan temukan tautan untuk jawabannya. stackoverflow.com/a/55216763/4079716
Nayan Patel
2

Sudahkah Anda mempertimbangkan Promise.prototype.finally()?

Tampaknya dirancang untuk melakukan persis apa yang Anda inginkan - menjalankan fungsi setelah semua janji telah diselesaikan (diselesaikan / ditolak), terlepas dari beberapa janji yang ditolak.

Dari dokumentasi MDN :

Itu finally() Metode dapat berguna jika Anda ingin melakukan beberapa pengolahan atau pembersihan setelah janji tersebut diselesaikan, terlepas dari hasilnya.

The finally()Metode ini sangat mirip dengan memanggil .then(onFinally, onFinally)namun ada beberapa perbedaan:

Saat membuat fungsi inline, Anda bisa melewatkannya sekali, alih-alih dipaksa untuk mendeklarasikannya dua kali, atau membuat variabel untuknya.

Akhirnya panggilan balik tidak akan menerima argumen apa pun, karena tidak ada cara yang dapat diandalkan untuk menentukan apakah janji itu dipenuhi atau ditolak. Kasus penggunaan ini tepat ketika Anda tidak peduli tentang alasan penolakan, atau nilai pemenuhan, dan karenanya tidak perlu menyediakannya.

Tidak seperti Promise.resolve(2).then(() => {}, () => {})(yang akan diselesaikan dengan undefined), Promise.resolve(2).finally(() => {})akan diselesaikan dengan 2. Demikian pula, tidak seperti Promise.reject(3).then(() => {}, () => {})(yang akan dipenuhi dengan undefined), Promise.reject(3).finally(() => {})akan ditolak dengan 3.

== Fallback ==

Jika versi JavaScript Anda tidak mendukung, Promise.prototype.finally()Anda dapat menggunakan solusi ini dari Jake Archibald :Promise.all(promises.map(p => p.catch(() => undefined)));

Tom Auger
sumber
1
Ya, sampai Promises.allSettled()benar-benar dilaksanakan (didokumentasikan oleh MDN di sini ), maka Promises.all.finally()tampaknya akan mencapai hal yang sama. Saya akan mencobanya ...
jamess
@ joess Kenapa kamu tidak membuat komentar ini sebagai jawaban yang tepat? Tidak ada jawaban yang merujuk pada ES6 allSettled().
Pravin
@ Pilravin - Dari apa yang saya tahu, allSettled()belum diterapkan di mana pun (belum), jadi saya tidak ingin maju dari kenyataan. Saya sukses dengan itu Promises.all(myPromiseArray).finally(), dan itu cocok dengan jawaban ini. Setelah allSettled()benar-benar ada, maka saya dapat mengujinya dan mencari tahu cara kerjanya. Sampai saat itu, siapa yang tahu apa yang sebenarnya akan diterapkan browser? Kecuali jika Anda memiliki info terbaru yang bertentangan ...
jamess
@ joess Benar bahwa ini masih dalam tahap konsep .. Namun FF dan chrome terbaru tampaknya mendukung sepenuhnya .. Tidak yakin stabilitasnya .. Mozilla Docs Bagaimanapun yang saya coba buat adalah bahwa itu akan lebih mudah untuk menemukan jika itu adalah jawaban dari komentar .. itu panggilan Anda :)
pravin
@pravin - Pada saat saya memposting komentar saya, itu tidak diterapkan di mana pun. Saya baru saja menguji di Firefox dan Chrome: Promise.allSettledtidak diterapkan di Firefox, tetapi tampaknya ada di Chrome. Hanya karena dokumen mengatakan itu diterapkan bukan berarti itu benar-benar diterapkan. Saya tidak akan menggunakannya dalam waktu dekat.
jamess
0

Bergantian, jika Anda memiliki kasus di mana Anda tidak terlalu peduli tentang nilai-nilai janji yang diselesaikan ketika ada satu kegagalan tetapi Anda masih ingin mereka berjalan, Anda bisa melakukan sesuatu seperti ini yang akan diselesaikan dengan janji-janji seperti biasa ketika mereka semua berhasil dan menolak dengan janji-janji yang gagal ketika salah satu dari mereka gagal:

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)
      }
    }
  )
}
Eric
sumber
0

Anda selalu dapat membungkus janji Anda mengembalikan fungsi dengan cara mereka menangkap kegagalan dan mengembalikan bukan nilai yang disepakati (misalnya error.message), sehingga pengecualian tidak akan menggulung sampai ke fungsi Promise.all dan menonaktifkannya.

async function resetCache(ip) {

    try {

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

    }catch (e) {

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

}
Tamir Nakar
sumber
0

Saya telah menemukan cara (penyelesaian) untuk melakukan ini tanpa membuatnya disinkronkan.

Jadi seperti yang disebutkan sebelumnya Promise.alltidak ada sama sekali.

jadi ... Gunakan janji terlampir untuk menangkap dan memaksakan tekad.


      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)
Juan Sebastian Contreras Aceve
sumber
0

Anda perlu tahu cara mengidentifikasi kesalahan dalam hasil Anda. Jika Anda tidak memiliki kesalahan standar yang diharapkan, saya sarankan Anda menjalankan transformasi pada setiap kesalahan di blok tangkap yang membuatnya dapat diidentifikasi dalam hasil Anda.

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
  }
Anthony Awuley
sumber
0

Bukan cara terbaik untuk membuat kesalahan log, tetapi Anda selalu dapat mengatur semuanya ke array untuk janji, dan menyimpan hasil yang dihasilkan ke dalam variabel baru.

Jika Anda menggunakan graphQL, Anda perlu memposting proses tanggapan terlepas dan jika tidak menemukan referensi yang benar itu akan merusak aplikasi, mempersempit di mana masalahnya berada

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;
Vincent Tang
sumber
-1

Begitulah cara Promise.alldirancang untuk bekerja. Jika satu janji reject(), seluruh metode segera gagal.

Ada kasus penggunaan di mana seseorang mungkin ingin memiliki Promise.allmemungkinkan untuk janji gagal. Untuk mewujudkannya, jangan gunakan reject()pernyataan apa pun dalam janji Anda. Namun, untuk memastikan aplikasi / skrip Anda tidak membeku seandainya ada janji tunggal yang mendasari tidak pernah mendapat tanggapan, Anda perlu memberi batas waktu padanya.

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);
        });
    });
}
Ronnie Royston
sumber
inilah jawabannya: stackoverflow.com/questions/31424561/…
Humoyun Ahmad
Tidak menggunakan reject()dalam janji Anda baik-baik saja, tetapi bagaimana jika Anda perlu menggunakan janji perpustakaan lain?
Dan Dascalescu
-8

Saya menulis perpustakaan npm untuk mengatasi masalah ini lebih indah. https://github.com/wenshin/promiseallend

Install

npm i --save promiseallend

2017-02-25 api baru, itu tidak melanggar prinsip janji

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 buruk tua, jangan gunakan itu!

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'}
Wenshin
sumber
Bagaimana cara kerjanya? Tolong tunjukkan dan jelaskan penerapan fungsi Anda.
Bergi
Saya menulis logika konkuren baru seperti Promise.all. Tapi itu akan mengumpulkan semua data dan kesalahan dari setiap janji. juga mendukung input objek, bukan itu intinya. setelah mengumpulkan semua data dan kesalahan, saya mengganti promise.thenmetode untuk menangani callback terdaftar yang termasuk ditolak dan dipenuhi. Untuk detail Anda dapat melihat kode
wenshin
Eh, kode itu akan memanggil keduanya onFulfilleddan onRejectedpenangan yang diteruskan ke then?
Bergi
Ya, hanya ketika status janji dicampur fulfilleddan rejected. Tapi itu benar-benar menyebabkan masalah sulit untuk kompatibel dengan semua kasus penggunaan janji secara normal, seperti onFulfilleddan onRejectedsemua kembali Promise.reject()atau Promise.resolve(). Sejauh ini saya tidak jelas bagaimana menyelesaikannya, apakah ada yang punya ide yang lebih baik? Jawaban terbaik untuk saat ini memiliki masalah adalah, mungkin tidak dapat menyaring data dan kesalahan di lingkungan browser.
Wenshin
Apakah kita perlu menginstal modul npm dengan pengelola paket python pip?
sevenfourk