कॉलबैक की प्रतीक्षा में Node.js को बाहर निकलने से कैसे रोकें?


96

मेरे पास इस तरह का कोड है:

var client = new mysql.Client(options);
console.log('Icanhasclient');

client.connect(function (err) {
  console.log('jannn');
  active_db = client;
  console.log(err);
  console.log('hest');

  if (callback) {
    if (err) {
      callback(err, null);
    }

    callback(null, active_db);
  }
});

मेरी समस्या यह है कि जब मैं इसे चलाता हूं तो नोड तुरंत समाप्त हो जाता है। यह 'Icanhasclient' को प्रिंट करता है, लेकिन कॉलबैक के अंदर कोई भी कंसोल नहीं है।

(इस उदाहरण में mysql नोड- mysql है

क्या ऐसा कुछ है जो नोड बनाने के लिए किया जा सकता है। बाहर निकलने से पहले कॉलबैक के पूरा होने की प्रतीक्षा करें?


1
आपका मतलब क्या है बाहर निकलने से रोकें? जब तक सभी कॉलबैक पूरे नहीं हो जाते तब तक नोड्स बाहर नहीं निकलते। यह एक एकल प्रक्रिया है।
नेबज

4
@nEEbz: अगर ऐसा था, तो कॉलबैक को निष्पादित किए बिना मेरी स्क्रिप्ट बाहर क्यों निकलती है?
मिकाल

यह आपके डेटाबेस से जुड़ने के साथ कुछ समस्या है; मुझे यकीन नहीं है कि यह कॉलबैक फायरिंग क्यों नहीं है। क्या यह कोई त्रुटि देता है?
नेबज

नहीं, यह बस चुपचाप विफल रहता है :(
मिकल

यह बहुत अजीब है। मुझे उम्मीद है कि हमें इसका जवाब मिल जाएगा।
नीबज

जवाबों:


50

कॉलबैक कतारबद्ध नहीं है

नोड तब तक चलता है जब तक कि सभी ईवेंट कतार खाली न हो जाएं। कॉलबैक को इवेंट कतार में जोड़ा जाता है जब कोई कॉल जैसे

  emmiter1.on('this_event',callback).

निष्पादित किया गया है। यह कॉल मॉड्यूल डेवलपर द्वारा लिखे गए कोड का हिस्सा है।

यदि कोई मॉड्यूल सिंक्रोनस / ब्लॉकिंग संस्करण से एक त्वरित पोर्ट है, तो ऐसा नहीं हो सकता है कि ऑपरेशन का कुछ हिस्सा पूरा हो गया है और ऐसा होने से पहले सभी कतारें खाली हो सकती हैं, नोड को चुपचाप बाहर निकलने की अनुमति देता है।

यह एक डरपोक बग है, यह वह है जो मॉड्यूल डेवलपर विकास के दौरान नहीं चल सकता है, क्योंकि यह व्यस्त सिस्टम में कई कतारों के साथ कम बार होगा क्योंकि यह उन सभी के लिए दुर्लभ होगा जो महत्वपूर्ण समय पर खाली होंगे।

उपयोगकर्ता के लिए एक संभावित फिक्स / बग डिटेक्टर संदिग्ध फ़ंक्शन कॉल से पहले एक विशेष टाइमर इवेंट सम्मिलित करना है।


"ऐसा नहीं हो सकता है कि ऑपरेशन का कुछ हिस्सा पूरा हो गया है" - क्या आप इसे स्पष्ट कर सकते हैं? क्या आप कह रहे हैं कि कोड का एक टुकड़ा अभी भी चल रहा है, इससे पहले कि यह घटना कतार में कॉलबैक जोड़ने का मौका है, छोड़ सकता है?
BT

मुझे लगता है कि उसका मतलब है कि यदि पुस्तकालय ने कोड को एक बार एक नए अतुल्यकालिक संस्करण के रूप में बदल दिया है, तो संभव है कि पुस्तकालय निर्माता कॉलबैक की कतार लगाना भूल गए और घटना की कतारें आपके निष्पादन के बीच में कहीं खाली हो जाएं, इस तरह से समाप्त नहीं हुईं। कॉलबैक।
डायल्सन सेल्स

1
क्या इस मुद्दे को मज़बूती से पुन: पेश करने का एक आसान तरीका है?
जॉर्डन कुंड

इसके लिए धन्यवाद! मेरे पास एक "लटकी हुई" प्रक्रिया थी और समझ में नहीं आया कि यह क्यों नहीं चलेगा। मेरे सभी श्रोताओं / ईवेंट कॉलबैक को साफ करने के बाद, प्रक्रिया से बाहर निकल गया।
ps2goat

7
चेतावनी - बहुत सारे अपवोट होने के बावजूद, मुझे लगता है कि इस उत्तर में जानकारी गलत है। कॉलिंग EventEmitter.on()करता नहीं घटना पाश कि नोड (नोड के वर्तमान संस्करण में कम से कम) के लिए इंतजार करेंगे पर कुछ भी जोड़ने। लगता है कि टाइमआउट सेट करने और कोर लाइब्रेरी से एसिंक्स कॉल करने जैसी चीजें ही ऐसा कर सकती हैं। आप एक लाइन प्रोग्राम को लिखकर आसानी से इसका परीक्षण कर सकते हैं जो एक ऐसी घटना की उम्मीद करता है जो कभी भी आग नहीं लगाएगा। इस जवाब से, आप इसे समाप्त करने के लिए कभी नहीं उम्मीद थी, लेकिन यह करता है तुरन्त समाप्त। अधिक जानकारी के लिए यह उत्तर देखें
डेवनिकविल

40

आप बस एक सेट टाइमआउट जारी कर सकते हैं या सेटइंटरवल के साथ एक पुनरावृत्ति टाइमआउट कर सकते हैं।

यदि आप बाहर निकलने की स्थिति की जांच करना चाहते हैं, तो आप एक सशर्त समय-सीमा भी कर सकते हैं:

(function wait () {
   if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000);
})();

इसे अपने कोड के अंत में रखें और कंसोल केवल प्रतीक्षा करेगा ... और प्रतीक्षा करें ... जब तक आप इसे बंद नहीं करना चाहते।


5
यह एक अच्छा समाधान है, लेकिन एक सुंदर समाधान नहीं है (जो आपकी गलती नहीं है, लेकिन नोड का है)।
पेटेर -

14

मेरा समाधान एक EventEmitter को तुरंत करना था, और मेरे कस्टम इवेंट के लिए सुनना था।

var eventEmitter = new process.EventEmitter();

तब मुझे eventEmitter.emitasync कॉलबैक से कॉल किया गया:

client.connect(function (err) {
    eventEmitter.emit('myevent', {something: "Bla"})
});

मेरी स्क्रिप्ट में आखिरी चीज़ थी eventEmitter.on:

eventEmitter.on('myevent', function(myResult){
  // I needed the result to be written to stdout so that the calling process could get it
  process.stdout.write(JSON.stringify(myResult));
});

नोड तब तक प्रतीक्षा करेगा जब तक कि ईवेंट हैंडलर खत्म नहीं हो जाता।


1
मैं `प्रक्रिया हो रही है। EventEmitter एक constructor` त्रुटि नहीं है। आप क्या सुझाव देंगे?
एंथोनी कोंग

EventEmitter बनाने का तरीका देखें। coligo.io/nodejs-event-emitter एक अच्छे संसाधन की तरह लगता है। यह हो सकता है कि नोड के अलग-अलग संस्करण बदल गए हैं कि एक कैसे बनाया जाए।
you786

2
EventEmitterवर्ग eventsमॉड्यूल द्वारा परिभाषित किया गया है। तो, एक नया एमिटर बनाने के लिए const EventEmitter = require('events'); var eventEmitter = new EventEmitter():।
सेडएक्स

1
चेतावनी - स्वीकृत उत्तर पर मेरी टिप्पणी देखें। मुझे लगता है कि यह गलत है, और नोड के वर्तमान संस्करण के लिए कम से कम काम नहीं करता है।
डेवनिकविल

5

@ टॉड के उत्तर के आधार पर, मैंने एक-लाइनर बनाया। इसे अपनी स्क्रिप्ट की शुरुआत में शामिल करें, और सेट करें done = trueजब आप कर रहे हैं:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

उदाहरण:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

someAsyncOperation().then(() => {
  console.log('Good to go!');
  done = true;
});

यह कैसे काम करता है? यदि हम इसे थोड़ा बढ़ाएँ:

// Initialize the variable `done` to `undefined`
// Create the function wait, which is available inside itself
// Note: `var` is hoisted but `let` is not so we need to use `var`
var done = (function wait () {

  // As long as it's nor marked as done, create a new event+queue
  if (!done) setTimeout(wait, 1000);

  // No return value; done will resolve to false (undefined)
})();

1
आप IIFE के आउटपुट पर क्यों सेट हो रहे हैं, बस गलत उसके बाद IIFE के साथ बेहतर होगा।
टिफन

1
@ टिफन शायद सिर्फ इसे वन-लाइनर बनाने के लिए।
पेड्रो ए

0

यहाँ मेरे दो सेंट हैं:

async function main()
{
    await new Promise(function () {});
    console.log('This text will never be printed');
}

function panic(error)
{
    console.error(error);
    process.exit(1);
}

// https://stackoverflow.com/a/46916601/1478566
main().catch(panic).finally(clearInterval.bind(null, setInterval(a=>a, 1E9)));

0

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

function wrapPromiseMain(entryPoint) {
    const pollTime = 1000000;
    let interval = setInterval(() => {}, pollTime);
    
    return entryPoint().finally(() => {clearInterval(interval)});
}

इसका उपयोग करने के लिए, बस अपने मुख्य प्रवेश बिंदु का वादा करें और इसे आवरण के तर्क के रूप में पास करें:

function main() {

    // ... main stuff ...

    return doSomethingAsync();
}

wrapPromiseMain(main);

मुझे यह मूल मतदान छोरों की तुलना में थोड़ा सा कठिन लगता है क्योंकि यह वादा पूरा होने पर टाइमर को स्वतः रद्द कर देगा, इसलिए इसमें कोई अतिरिक्त विलंबता नहीं है। इसलिए मतदान का समय मूल रूप से हमेशा के लिए हो सकता है यदि आप इसे चाहते हैं।


नोट: पोस्ट करने के बाद संपादित किया गया क्योंकि मुझे एहसास हुआ कि मैं सेटटाइम करने के लिए जंजीर कॉल के बजाय सेटइंटरवल का उपयोग करके इसे और भी संक्षिप्त बना सकता हूं।
ad1c371f7d05

-1

मैंने felixge / node-mysql लाइब्रेरी को देखा और कमांड क्लाइंट का संदर्भ नहीं देखा। API में कनेक्ट करें। क्या यह वास्तविक कॉल है जिसे आप बनाने की कोशिश कर रहे हैं (यहां नाइटपिक होने की कोशिश नहीं कर रहे हैं)? भले ही, IMHO आपको इस बारे में अधिक सोचने की ज़रूरत है कि जावास्क्रिप्ट कैसे डिज़ाइन किया गया है, क्योंकि यह अन्य अन्य लोकप्रिय भाषाओं की तुलना में अलग प्रोग्रामिंग प्रतिमान का उपयोग करता है।

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

    var myCallback(err, response) {
      if (err) {
        console.log('err:%s',err);
      } else {
        console.log('response:%s',response);
      }
    }

    client.connect(err, function(response) {
      // this anonymous function is the callback to client.connect, the var
      // 'callback' would be undefined.
      if (err) {
        myCallback(err);
        return; // Explicit call to return, else the lines below would run.
      } 
      myCallback(null, response);
    });

दूसरा, यदि आप स्पष्ट रूप से जावास्क्रिप्ट के भीतर रिटर्न नहीं कहते हैं, तो फ़ंक्शन जारी रहेगा। मैं खुद इस बात से कन्नी काट गया । अंत में, जावास्क्रिप्ट एक ईवेंट-चालित लूप चलाता है जिसका अर्थ है कि यह मानों को वापस करने के लिए फ़ंक्शंस का कभी इंतजार नहीं करेगा, यही वजह है कि हमारे पास ये सभी कॉलबैक पहले स्थान पर हैं। आप जावास्क्रिप्ट को अलग तरह से व्यवहार करने के लिए मजबूर कर सकते हैं, उदाहरण के लिए जब तक कि एक शर्त सही न हो तब तक लूप का उपयोग करके। इवेंट लूप में हेरफेर करने की विभिन्न रणनीतियों के लिए, caolan द्वारा 'async' लाइब्रेरी देखें । इन तरीकों को अति प्रयोग करने का प्रमुख नुकसान यह है कि वास्तव में सीपीयू चक्रों को अवरुद्ध करना / अवरुद्ध करना जब आपको संभवतः अधिक कॉलबैक का उपयोग करना चाहिए और बस फिर से सोचना चाहिए कि आपके प्रोग्राम कैसे काम करते हैं।


-2

कृपया यह प्रयास करें। अगर यह मदद की जाँच करें।

var client = new mysql.Client(options);
console.log('Icanhasclient');
var verbose;

if (!verbose) {
    return new Promise(function (resolve, reject) {
        client.connect(function (err) {
            if (err) {
                console.log(Error in connecting
                SQL ${err}
            )
                ;
                return reject(err);
            }
            verbose = client;
            return resolve(verbose);
        })
    })
} else {
    return new Promise(function (resolve) {
        resolve(verbose);
    })
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.