NodeJS UnhandledPromiseRejectionWarning


134

इसलिए, मैं एक घटक का परीक्षण कर रहा हूं जो एक घटना-एमिटर पर निर्भर करता है। ऐसा करने के लिए मैं मोचा + चाय के साथ वादों का उपयोग कर एक समाधान के साथ आया:

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
    done();
  }).catch((error) => {
    assert.isNotOk(error,'Promise error');
    done();
  });
});

कंसोल पर मुझे 'UnhandledPromiseRejectionWarning' मिल रहा है, भले ही अस्वीकार फ़ंक्शन को कॉल किया जा रहा हो, क्योंकि यह तुरंत संदेश 'AssertionError: Promise error' दिखाता है

:

और फिर, 2 सेकंड के बाद मुझे मिलता है

त्रुटि: 2000 मी से अधिक का समय समाप्त। सुनिश्चित करें कि इस परीक्षण में कॉलबैक किया जा रहा है।

कैच कॉलबैक निष्पादित होने के बाद से यह भी अजीब है। (मुझे लगता है कि किसी कारण से एस्टर विफलता ने बाकी निष्पादन को रोक दिया)

अब मजेदार बात है, अगर मैं टिप्पणी करता हूं assert.isNotOk(error...)कि परीक्षण कंसोल में किसी भी चेतावनी के साथ ठीक चलता है। यह इस अर्थ में 'विफल' है कि यह कैच को अंजाम देता है।
लेकिन फिर भी, मैं इन त्रुटियों को वादे के साथ नहीं समझ सकता। क्या कोई मुझे बता सकता है?


मुझे लगता है कि आपके पास अंतिम पंक्ति में ब्रेस और पैरेंस को बंद करने का एक अतिरिक्त सेट है। कृपया उन्हें हटा दें और पुनः प्रयास करें।
रेडू

4
यह बहुत अच्छा है, नए अनहेल्ड रिजेक्शन की चेतावनी वास्तविक जीवन में बग ढूंढती है और लोगों का समय बचाती है। यहां इतनी जीत। इस चेतावनी के बिना आपके परीक्षण बिना किसी स्पष्टीकरण के समाप्त हो जाएंगे।
बेंजामिन ग्रुएनबाम सेप

जवाबों:


161

इस समस्या के कारण होता है:

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

यदि दावा विफल हो जाता है, तो यह एक त्रुटि फेंक देगा। इस त्रुटि का कारण done()कभी नहीं कहा जाएगा, क्योंकि इससे पहले कोड गलत है। यही कारण है कि मध्यांतर।

"बिना क्रिया वादा अस्वीकृति" भी, विफल हुए दावे के कारण होता है क्योंकि एक त्रुटि एक में फेंक दिया जाता है, तो catch()हैंडलर, और वहाँ बाद में एक नहीं है catch()हैंडलर , त्रुटि निगल लिया जाएगा (के रूप में में विस्तार से बताया इस लेख )। UnhandledPromiseRejectionWarningचेतावनी इस तथ्य के लिए आपको चेतावनी है।

सामान्य तौर पर, यदि आप मोचा में वादा-आधारित कोड का परीक्षण करना चाहते हैं, तो आपको इस तथ्य पर भरोसा करना चाहिए कि मोचा खुद पहले से ही वादों को संभाल सकता है। आपको उपयोग नहीं करना चाहिए done(), बल्कि इसके बजाय, अपने परीक्षण से एक वादा वापस करें। मोचा फिर किसी भी त्रुटि को पकड़ लेगा।

ऐशे ही:

it('should transition with the correct event', () => {
  ...
  return new Promise((resolve, reject) => {
    ...
  }).then((state) => {
    assert(state.action === 'DONE', 'should change state');
  })
  .catch((error) => {
    assert.isNotOk(error,'Promise error');
  });
});

7
जिज्ञासु के लिए, चमेली के लिए भी यह सच है।
निक रेडफोर्ड

@robertklep नहीं पकड़ेंगे किसी भी त्रुटि के लिए बुलाया जाएगा और न केवल एक आप की उम्मीद कर रहे हैं? मुझे लगता है कि यदि आप विफलताओं पर जोर देने की कोशिश कर रहे हैं तो यह शैली काम नहीं करेगी।
theCrazyProgrammer

1
@ TheCrazyProgrammer catchहैंडलर को संभवतः दूसरे तर्क के रूप में पारित किया जाना चाहिए then। हालांकि, मुझे पूरी तरह से यकीन नहीं है कि ओपी का इरादा क्या था, इसलिए मैंने इसे छोड़ दिया।
रॉबर्टक्लेप

1
और चमेली के बारे में उत्सुक किसी के लिए भी, done.fail('msg')इस मामले में उपयोग करें।
पावेल

क्या आप इस बात का पूरा उदाहरण दे सकते हैं कि मुख्य कोड बनाम अभिकथन कहाँ जाना चाहिए, यहाँ इतना स्पष्ट नहीं है ..... खासकर यदि आप हमारे कोड में मूल सेवा / वादा कॉल से एक मूल्य का दावा करते हैं। क्या हमारे कोड के लिए वास्तविक वादा इस अन्य "मोचा वादा" के भीतर जाता है ??
bjm88 16

10

मुझे यह त्रुटि तब हुई जब मैं सिनॉन से लड़ रहा था।

फिक्स का उपयोग npm पैकेज साइनॉन-एश-वादा करने के लिए किया जाता है, जब स्टब्स के साथ वादों को हल करना या अस्वीकार करना।

के बजाय ...

sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') ))

उपयोग ...

require('sinon-as-promised');
sinon.stub(Database, 'connect').rejects(Error('oops'));

एक रिज़ॉल्यूशन विधि भी है (नोट को अंत पर ध्यान दें)।

Http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections देखें


1
सिनॉन में अब संस्करण 2 के रूप में स्टब्स के लिए " रिज़ॉल्यूशन " और "अस्वीकार" शामिल हैंnpmjs.com/package/sinon-as-promised देखें । मैंने फिर भी + 1 जवाब दिया, हालांकि - मुझे इस बारे में पता नहीं था।
एंड्रयू

9

मोक्ष में मुखर पुस्तकालय एक त्रुटि फेंक कर काम करते हैं यदि अभिकथन सही नहीं था। catchविधि के लिए प्रदान किए गए निष्पादक फ़ंक्शन में फेंक दिए जाने पर भी एक त्रुटि परिणाम को फेंकने का वादा किया जाता है।

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

ऊपर दिए गए कोड में errorआपत्ति का मूल्यांकन करने के लिए trueतो जोर पुस्तकालय में एक त्रुटि फेंकता है ... जो कभी पकड़ा नहीं जाता है। त्रुटि के परिणामस्वरूप doneविधि को कभी नहीं कहा जाता है। मोचा का doneकॉलबैक इन त्रुटियों को स्वीकार करता है, इसलिए आप मोचा में सभी वादे की श्रृंखला को समाप्त कर सकते हैं .then(done,done)। यह सुनिश्चित करता है कि किए गए तरीके को हमेशा कहा जाता है और त्रुटि उसी तरह से रिपोर्ट की जाएगी जब मोचा तुल्यकालिक कोड में मुखर त्रुटि को पकड़ लेता है।

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then(((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
  })).then(done,done);
});

मोचा में वादों का परीक्षण करते समय .then (किया, किया) का उपयोग करने के विचार के लिए मैं इस लेख को श्रेय देता हूं ।


6

जो लोग UnhandledPromiseRejectionWarningपरीक्षण वातावरण के बाहर त्रुटि / चेतावनी की तलाश कर रहे हैं , उनके लिए यह शायद इसलिए हो सकता है क्योंकि कोड में कोई भी एक वादे में अंतिम त्रुटि की देखभाल नहीं कर रहा है:

उदाहरण के लिए, यह कोड इस प्रश्न में दी गई चेतावनी दिखाएगा:

new Promise((resolve, reject) => {
  return reject('Error reason!');
});

(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!

और .catch()त्रुटि को जोड़ना या संभालना चेतावनी / त्रुटि को हल करना चाहिए

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).catch(() => { /* do whatever you want here */ });

या thenफ़ंक्शन में दूसरे पैरामीटर का उपयोग कर रहा है

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });

1
बेशक, लेकिन मुझे लगता है कि वास्तविक जीवन में हम आमतौर पर सिर्फ new Promise((resolve, reject) => { return reject('Error reason!'); })फ़ंक्शन का उपयोग नहीं करते हैं, function test() { return new Promise((resolve, reject) => { return reject('Error reason!'); });}इसलिए फ़ंक्शन के अंदर हमें उपयोग करने की आवश्यकता नहीं है, .catch()लेकिन त्रुटियों को सफलतापूर्वक संभालने के लिए यह उस फ़ंक्शन test().catch(e => console.log(e))या async / प्रतीक्षा संस्करण का उपयोग करते समय पर्याप्त हैtry { await test() } catch (e) { console.log(e) }
mikep

1

मैंने इस मुद्दे का सामना किया:

: भविष्य में, अस्वीकार किए गए वादे को अस्वीकार कर दिया जाता है जो गैर-शून्य निकास कोड के साथ नोड की प्रक्रिया को समाप्त कर देंगे।

यह मेरी गलती थी, मैं resऑब्जेक्ट को बदल रहा था then(function(res), इसलिए resपरिणाम में बदल गया और अब यह काम कर रहा है।

गलत

module.exports.update = function(req, res){
        return Services.User.update(req.body)
                .then(function(res){//issue was here, res overwrite
                    return res.json(res);
                }, function(error){
                    return res.json({error:error.message});
                }).catch(function () {
                   console.log("Promise Rejected");
              });

भूल सुधार

module.exports.update = function(req, res){
        return Services.User.update(req.body)
                .then(function(result){//res replaced with result
                    return res.json(result);
                }, function(error){
                    return res.json({error:error.message});
                }).catch(function () {
                   console.log("Promise Rejected");
              });

सेवा कोड:

function update(data){
   var id = new require('mongodb').ObjectID(data._id);
        userData = {
                    name:data.name,
                    email:data.email,
                    phone: data.phone
                };
 return collection.findAndModify(
          {_id:id}, // query
          [['_id','asc']],  // sort order
          {$set: userData}, // replacement
          { "new": true }
          ).then(function(doc) {
                if(!doc)
                    throw new Error('Record not updated.');
                return doc.value;   
          });
    }

module.exports = {
        update:update
}

1

यहाँ E7 async / प्रतीक्षा के साथ मेरा अनुभव है :

मामले में आपको async helperFunction()अपने परीक्षण से बुलाया जाता है ... (ईएस 7 asyncकीवर्ड के साथ एक खोज , मेरा मतलब है)

→ सुनिश्चित करें, आप कहते हैं कि await helperFunction(whateverParams) (अच्छी तरह से, हाँ, स्वाभाविक रूप से, एक बार जब आप जानते हैं ...)

और इसके लिए काम करने के लिए ('वेट एक आरक्षित शब्द है' से बचने के लिए), आपके परीक्षण-कार्य में एक बाहरी async मार्कर होना चाहिए:

it('my test', async () => { ...

4
आपको इसे कॉल करने की आवश्यकता नहीं हैawait helperFunction(...) । एक asyncफ़ंक्शन एक वादा लौटाता है। आप बस दिए गए वादे को संभाल सकते हैं जैसे आप एक फ़ंक्शन पर asyncकरेंगे जो चिह्नित नहीं है जो एक वादा वापस करने के लिए होता है। मुद्दा वादा, अवधि को संभालने का है। फ़ंक्शन होता है asyncया नहीं, इससे कोई फर्क नहीं पड़ता। वादा निभाने के कई तरीकों में से awaitकेवल एक है
लुई

1
सच। लेकिन फिर मुझे पकड़ने पर लाइनों का निवेश करना होगा ... या मेरे परीक्षण झूठे सकारात्मक के रूप में गुजरते हैं, और किसी भी असफल वादे (परीक्षण के परिणामों के संदर्भ में) अव्यवस्थित हो जाएंगे। इसलिए इंतजार मुझे कम लाइनों और प्रयास की तरह लगता है। - वैसे भी, इंतजार करना भूल गया था, क्या कारण है कि UnhandledPromiseRejectionWarningमेरे लिए ... इस प्रकार यह जवाब।
फ्रैंक नॉक

0

मुझे सेलेनियम के लिए चाई-वेबड्राइवर के साथ एक समान अनुभव था। मैंने awaitदावे में जोड़ा और इसने इस मुद्दे को तय किया:

ककड़ी का उपयोग करके उदाहरण:

Then(/I see heading with the text of Tasks/, async function() {
    await chai.expect('h1').dom.to.contain.text('Tasks');
});

-7

मैंने वेबपैक (प्रतिक्रिया js समस्या) की स्थापना रद्द करने के बाद इस समस्या को हल किया।

sudo uninstall webpack
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.