İşlenmemiş bir vaat reddi nedir?


204

Açısal 2 öğrenmek için eğitimlerini deniyorum.

Böyle bir hata alıyorum:

(node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r                                                                                                     ejection id: 1): Error: spawn cmd ENOENT
[1] (node:4796) DeprecationWarning: Unhandled promise rejections are deprecated.
In the future, promise rejections that are not handled will terminate the Node.
js process with a non-zero exit code.

Ben SO farklı sorular ve cevaplar geçti ama bir "İşlenmemiş Promise Reddetme" ne olduğunu bulamadım.

Birisi bana ne olduğunu ve ne Error: spawn cmd ENOENTolduğunu, ne zaman ortaya çıktığını ve bu uyarıdan kurtulmak için neyi kontrol etmem gerektiğini açıklayabilir mi?


2
Bu soruyu kaçırdım! Bu uyarı için çok üzgünüm - yeni Node.js'de gerçekten geliştirdik ve yakında her şeyi çok daha iyi hale getireceğiz!
Benjamin Gruenbaum


@BenjaminGruenbaum, henüz düzeltilmedi mi? Aynı hatayı v12.16.1 düğümünde aldım
Bebek desta

1
@Babydesta, artık yığın izlemesinde daha iyi bir hata gösteriyoruz, ancak işlenmeyen reddetmelerde düğümü hala çökmüyoruz. Muhtemelen bunu yapmak için sadece bir PR açmamız gerekiyor.
Benjamin Gruenbaum

Yanıtlar:


200

Bu hatanın kaynağı, her bir vaadin vaat reddini işlemesi beklendiği gerçeğinde yatmaktadır, yani .catch (...) . kodda bir vaat için aşağıda verilen gibi bir .catch (...) ekleyerek de bundan kaçınabilirsiniz .

örneğin, fonksiyon PTest () olacak gidermek veya global değişken değerine dayanarak reddetmek bir söz ya someVar

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
}).catch(function () {
     console.log("Promise Rejected");
});

Bazı durumlarda, "işlenmemiş söz reddi" mesajı, vaatler için .catch (..) yazmış olsak bile gelir. Her şey kodunuzu nasıl yazdığınızla ilgilidir. Aşağıdaki kod, işliyor olsak bile "işlenmemiş söz reddi" üretecektir catch.

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
});
// See the Difference here
myfunc.catch(function () {
     console.log("Promise Rejected");
});

Aradaki fark, .catch(...)zincir olarak değil ayrı olarak ele almanızdır. Bazı nedenlerden dolayı JavaScript motoru, ele alınamayan söz vermeyi reddetmeden söz vermiş gibi davranır.


4
myFunc = myFunct.then...İkinci örneğe eklerseniz işe yarıyor gibi görünüyor .
einstein

@einstein işe yarayacaktır çünkü ilk örnekte olduğu gibi aynı zinciri yeniden oluşturuyorsunuz:var x = foo(); x = x.then(...); x = x.catch(...)
randomsock

4
Eğer "un saplı söz reddi olmadan vaadi olarak Nedense Java Script motoru davranır onu" deyince @einstein sizin zincirsiz örnekte, bu olmadığı için ve istisna atılmış olabilir .then(() => {...})hangi değil taşıma? Bunun onları zincirlediğiniz zamanki gibi yaptığını sanmıyorum. Bu mu?
Simon Legg

8
@DKG İkinci noktanız catchiçin sözdizimi şekeri then(undefined, onRejected). Zaten o zaman myfunc üzerinde aradığınız ve bu bir hatayı tetiklediğinden, aynı sözü tekrar (undefined, onRejected) çağırmayacak.
Kevin Lee

1
Nerede değişmeli? İyonik cordova yapı andorid komutunu verdiğimde bana bu hatayı veren iyonik 3 kullanıyorum.
Sagar Kodte

35

Bu, bir çalıştırılan kodda a Promiseile tamamlandığında .reject()veya bir istisna atıldığında asyncve.catch() ve reddetmeyi işlemediğinde gerçekleşir.

Reddedilen bir söz, uygulama giriş noktasına doğru yükselen ve kök hata işleyicisinin bu çıktıyı üretmesine neden olan bir istisna gibidir.

Ayrıca bakınız


Nerede değişmeli? İyonik cordova yapı andorid komutunu verdiğimde bana bu hatayı veren iyonik 3 kullanıyorum.
Sagar Kodte

Bu bilgiyi söylemek zor. Minimal bir reprodüksiyon oluşturmayı ve özel durumunuz için yeni bir soru oluşturmanızı öneririm.
Günter Zöchbauer

bunun için ödül açtım. Lütfen şuna bakın stackoverflow.com/q/48145380/5383669
Sagar Kodte

22

Vaatler reddedildikten sonra "halledilebilir". Yani, yakalama işleyicisi sağlamadan önce bir sözün reddetme geri çağrısı çağrılabilir. Bu davranış benim için biraz rahatsız edici çünkü biri yazabilir ...

var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });

... ve bu durumda, Söz sessizce reddedilir. Bir catch işleyici eklemeyi unutursa, kod hatasız sessizce çalışmaya devam eder. Bu, kalıcı ve bulunması zor hatalara yol açabilir.

Node.js durumunda, bu işlenmemiş Promise reddi ile başa çıkma ve sorunları bildirme söz konusudur. Bu beni ES7 zaman uyumsuzluğuna / beklemeye getiriyor. Bu örneği düşünün:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  let temp = await tempPromise;
  // Assume `changeClothes` also returns a Promise
  if(temp > 20) {
    await changeClothes("warm");
  } else {
    await changeClothes("cold");
  }

  await teethPromise;
}

Yukarıdaki örnekte, getRoomTemperature gerçekleştirilmeden önce teethPromise'ın reddedildiğini (Hata: diş macunu bitti!) Varsayalım. Bu durumda, dişleri bekleyene kadar işlenmemiş bir Promise reddi olacaktır.

Demek istediğim bu ... işlenmemiş Promise reddini bir sorun olarak değerlendirirsek, daha sonra bir bekleyiş tarafından gerçekleştirilen Promise'ler yanlışlıkla hata olarak bildirilebilir. Daha sonra, işlenmemiş Promise reddetmelerinin sorunlu olmadığını düşünürsek, meşru hatalar bildirilmeyebilir.

Bunun üzerine düşünceler?

Bu, Node.js projesinde bulunan tartışma ile ilgilidir:

Varsayılan İşlenmeyen Ret Algılama Davranışı

kodu şu şekilde yazarsanız:

function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  return Promise.resolve(tempPromise)
    .then(temp => {
      // Assume `changeClothes` also returns a Promise
      if (temp > 20) {
        return Promise.resolve(changeClothes("warm"));
      } else {
        return Promise.resolve(changeClothes("cold"));
      }
    })
    .then(teethPromise)
    .then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}

GetReadyForBed çağrıldığında, eşzamanlı olarak başka bir vaatle aynı "işlenmemiş ret" hatasına sahip olacak (elbette motora bağlı olarak hiçbir şey olmayabilir) nihai (iade edilmez) vaadini yaratacaktır. (İşlevinizin hiçbir şey döndürmediğini çok garip buluyorum, bu da zaman uyumsuz işlevinizin tanımsız için bir söz verdiği anlamına geliyor.

Şu anda yakalamadan bir Söz veriyorum ve daha sonra bir tane eklersem, daha sonra ele aldığımda çoğu "işlenmeyen ret hatası" uygulaması aslında uyarıyı geri çeker. Başka bir deyişle, async / await "işlenmeyen ret" tartışmasını görebildiğim şekilde değiştirmiyor.

Bu tuzaktan kaçınmak için lütfen kodu şu şekilde yazın:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  var clothesPromise = tempPromise.then(function(temp) {
    // Assume `changeClothes` also returns a Promise
    if(temp > 20) {
      return changeClothes("warm");
    } else {
      return changeClothes("cold");
    }
  });
  /* Note that clothesPromise resolves to the result of `changeClothes`
     due to Promise "chaining" magic. */

  // Combine promises and await them both
  await Promise.all(teethPromise, clothesPromise);
}

Bunun işlenmemiş herhangi bir vaat reddini önlemesi gerektiğini unutmayın.


13

"Kullanımdan Kaldırma Uyarısı: İşlenmemiş söz verme reddi reddedildi"

TLDR: Bir söz vardır resolveve rejectbir yapıyor rejectbir var en azından zorunda kalacak, böylece, bu itiraz edildi işlemek için bir catch olmadan catchüst düzeyde.


2

Benim durumumda Promise hiçbir reddetme ile ne çözülmedi, çünkü Promise fonksiyonum bir istisna attı. Bu hata UnhandledPromiseRejectionWarning iletisine neden olur.


1

Bir söz açtığımda, eşzamansız bir işlev oluşturacağım. Eğer fonksiyon iyi giderse RESOLVE diyorum, o zaman akış RESOLVE işleyicisinde, THEN'de devam ediyor. İşlev başarısız olursa, REJECT öğesini çağırarak işlevi sonlandırın, akış CATCH'de devam eder.

Düğümde reddedilen işleyici reddedilir. Hatanız sadece bir uyarı ve ben node.js github içinde okudum. Bunu buldum.

DEP0018: İşlenmemiş söz reddi

Tür: Çalışma Zamanı

İşlenmemiş vaat reddi reddedildi. Gelecekte, ele alınmayan söz verme reddi, Node.js işlemini sıfır olmayan bir çıkış koduyla sonlandıracaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.