सेटटाइमआउट से एक वादा कैसे करें


96

यह एक वास्तविक समस्या नहीं है, मैं बस यह समझने की कोशिश कर रहा हूं कि वादे कैसे किए जाते हैं।

मुझे यह समझने की ज़रूरत है कि एक फ़ंक्शन के लिए एक वादा कैसे किया जाए जो सेटटाउट की तरह कुछ भी नहीं लौटाता है।

मान लीजिए कि मेरे पास है:

function async(callback){ 
    setTimeout(function(){
        callback();
    }, 5000);
}

async(function(){
    console.log('async called back');
});

मैं एक वादा कैसे कर सकता हूं जो तैयार asyncहोने के बाद वापस आ सकता setTimeoutहै callback()?

मुझे लगा कि यह मुझे कहीं ले जाएगा:

function setTimeoutReturnPromise(){

    function promise(){}

    promise.prototype.then = function() {
        console.log('timed out');
    };

    setTimeout(function(){
        return ???
    },2000);


    return promise;
}

लेकिन मैं इससे आगे नहीं सोच सकता।


क्या आप अपना खुद का वादा पुस्तकालय बनाने की कोशिश कर रहे हैं ?
टीजे क्राउडर

@TJCrowder मैं नहीं था, लेकिन मुझे लगता है कि अब वास्तव में वही है जो मैं समझने की कोशिश कर रहा था। कि एक पुस्तकालय यह कैसे करेगा
लैगिंगसर्लेक्स

@ लैगिंग: समझ में आता है, मैंने उत्तर के लिए एक उदाहरण मूल वादा कार्यान्वयन जोड़ा है।
टीजे क्राउडर

मुझे लगता है कि यह एक बहुत ही वास्तविक दुनिया की समस्या है और मुझे अपनी कंपनी के निर्माण के लिए एक बड़ी परियोजना का समाधान करना था। ऐसा करने के लिए बेहतर तरीके होने की संभावना थी, लेकिन मुझे अनिवार्य रूप से हमारे ब्लूटूथ स्टैक के लिए एक वादा के संकल्प में देरी करने की आवश्यकता थी। मैंने जो किया, उसे दिखाने के लिए नीचे पोस्ट करूँगा।
सनी-मित्तल

1
बस ध्यान दें कि 2017 में 'async' एक फंक्शन के लिए कुछ भ्रामक नाम है, जैसा कि आपके पास हो सकता हैasync function async(){...}
mikemaccana

जवाबों:


129

अपडेट (2017)

यहां 2017 में, प्रोमो को जावास्क्रिप्ट में बनाया गया है, उन्हें ES2015 कल्पना द्वारा जोड़ा गया (पॉलीफ़िल IE8-IE11 जैसे पुराने वातावरण के लिए उपलब्ध हैं)। वे जिस वाक्य-रचना के साथ गए थे, आप उस Promiseकंस्ट्रक्टर ( Promise निष्पादक ) में कॉलबैक का उपयोग करते हैं, जो वादे के रूप में वादे को अस्वीकार / अस्वीकार करने के लिए कार्य करता है।

सबसे पहले, चूंकि asyncअब जावास्क्रिप्ट में एक अर्थ है (भले ही यह कुछ संदर्भों में एक कीवर्ड है), मैं laterभ्रम से बचने के लिए फ़ंक्शन के नाम के रूप में उपयोग करने जा रहा हूं ।

मूल देरी

देशी वादों (या एक वफादार पॉलीफिल) का उपयोग करना इस तरह दिखेगा:

function later(delay) {
    return new Promise(function(resolve) {
        setTimeout(resolve, delay);
    });
}

ध्यान दें कि ब्राउज़र के लिए परिभाषाsetTimeout का एक ऐसा संस्करण माना जाता है जहां कॉलबैक के लिए कोई तर्क पारित नहीं होता है जब तक कि आप अंतराल के बाद उन्हें नहीं देते हैं (यह गैर-ब्राउज़र वातावरण में सच नहीं हो सकता है, और इसका उपयोग नहीं किया गया था फ़ायरफ़ॉक्स पर सच है, लेकिन अब है; यह क्रोम पर सच है और यहां तक ​​कि IE8 पर वापस)।setTimeout

मूल्य के साथ बुनियादी देरी

यदि आप चाहते हैं कि आपका फ़ंक्शन वैकल्पिक रूप से किसी भी अस्पष्ट-आधुनिक ब्राउज़र पर एक रिज़ॉल्यूशन मान पारित करें, जो आपको setTimeoutदेरी के बाद अतिरिक्त तर्क देने की अनुमति देता है और फिर कॉल करने पर उन लोगों को पास करता है, तो आप ऐसा कर सकते हैं (वर्तमान फ़ायरफ़ॉक्स और क्रोम; IE11 + , शायद बढ़त नहीं IE8 या IE9 ; IE10 के बारे में कोई विचार नहीं):

function later(delay, value) {
    return new Promise(function(resolve) {
        setTimeout(resolve, delay, value); // Note the order, `delay` before `value`
        /* Or for outdated browsers that don't support doing that:
        setTimeout(function() {
            resolve(value);
        }, delay);
        Or alternately:
        setTimeout(resolve.bind(null, value), delay);
        */
    });
}

यदि आप ES2015 + तीर फ़ंक्शंस का उपयोग कर रहे हैं, तो यह अधिक संक्षिप्त हो सकता है:

function later(delay, value) {
    return new Promise(resolve => setTimeout(resolve, delay, value));
}

या और भी

const later = (delay, value) =>
    new Promise(resolve => setTimeout(resolve, delay, value));

मूल्य के साथ रद्द करने योग्य विलंब

यदि आप समय-सीमा रद्द करना संभव बनाना चाहते हैं, तो आप सिर्फ एक वादा वापस नहीं कर सकते later, क्योंकि वादे रद्द नहीं किए जा सकते।

लेकिन हम cancelवादे के लिए एक विधि और एक सहायक के साथ आसानी से एक वस्तु वापस कर सकते हैं , और रद्द करने पर वादे को अस्वीकार कर सकते हैं:

const later = (delay, value) => {
    let timer = 0;
    let reject = null;
    const promise = new Promise((resolve, _reject) => {
        reject = _reject;
        timer = setTimeout(resolve, delay, value);
    });
    return {
        get promise() { return promise; },
        cancel() {
            if (timer) {
                clearTimeout(timer);
                timer = 0;
                reject();
                reject = null;
            }
        }
    };
};

लाइव उदाहरण:

const later = (delay, value) => {
    let timer = 0;
    let reject = null;
    const promise = new Promise((resolve, _reject) => {
        reject = _reject;
        timer = setTimeout(resolve, delay, value);
    });
    return {
        get promise() { return promise; },
        cancel() {
            if (timer) {
                clearTimeout(timer);
                timer = 0;
                reject();
                reject = null;
            }
        }
    };
};

const l1 = later(100, "l1");
l1.promise
  .then(msg => { console.log(msg); })
  .catch(() => { console.log("l1 cancelled"); });

const l2 = later(200, "l2");
l2.promise
  .then(msg => { console.log(msg); })
  .catch(() => { console.log("l2 cancelled"); });
setTimeout(() => {
  l2.cancel();
}, 150);


मूल उत्तर 2014 से

आमतौर पर आपके पास एक वादा पुस्तकालय होगा (आप खुद को लिखते हैं, या वहां से कई में से एक)। उस लाइब्रेरी में आमतौर पर एक ऑब्जेक्ट होगा जिसे आप बना सकते हैं और बाद में "हल" कर सकते हैं, और उस ऑब्जेक्ट में एक "वादा" होगा जिसे आप इससे प्राप्त कर सकते हैं।

फिर laterकुछ इस तरह देखना चाहेंगे:

function later() {
    var p = new PromiseThingy();
    setTimeout(function() {
        p.resolve();
    }, 2000);

    return p.promise(); // Note we're not returning `p` directly
}

सवाल पर एक टिप्पणी में, मैंने पूछा:

क्या आप अपना खुद का वादा पुस्तकालय बनाने की कोशिश कर रहे हैं?

और तुमने कहा था

मैं नहीं था, लेकिन मुझे लगता है कि अब वास्तव में वही है जो मैं समझने की कोशिश कर रहा था। कि एक पुस्तकालय यह कैसे करेगा

उस समझ की सहायता के लिए, यहाँ एक बहुत ही मूल उदाहरण है, जो दूरस्थ रूप से वादा-ए का अनुपालन नहीं करता है: लाइव कॉपी

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Very basic promises</title>
</head>
<body>
  <script>
    (function() {

      // ==== Very basic promise implementation, not remotely Promises-A compliant, just a very basic example
      var PromiseThingy = (function() {

        // Internal - trigger a callback
        function triggerCallback(callback, promise) {
          try {
            callback(promise.resolvedValue);
          }
          catch (e) {
          }
        }

        // The internal promise constructor, we don't share this
        function Promise() {
          this.callbacks = [];
        }

        // Register a 'then' callback
        Promise.prototype.then = function(callback) {
          var thispromise = this;

          if (!this.resolved) {
            // Not resolved yet, remember the callback
            this.callbacks.push(callback);
          }
          else {
            // Resolved; trigger callback right away, but always async
            setTimeout(function() {
              triggerCallback(callback, thispromise);
            }, 0);
          }
          return this;
        };

        // Our public constructor for PromiseThingys
        function PromiseThingy() {
          this.p = new Promise();
        }

        // Resolve our underlying promise
        PromiseThingy.prototype.resolve = function(value) {
          var n;

          if (!this.p.resolved) {
            this.p.resolved = true;
            this.p.resolvedValue = value;
            for (n = 0; n < this.p.callbacks.length; ++n) {
              triggerCallback(this.p.callbacks[n], this.p);
            }
          }
        };

        // Get our underlying promise
        PromiseThingy.prototype.promise = function() {
          return this.p;
        };

        // Export public
        return PromiseThingy;
      })();

      // ==== Using it

      function later() {
        var p = new PromiseThingy();
        setTimeout(function() {
          p.resolve();
        }, 2000);

        return p.promise(); // Note we're not returning `p` directly
      }

      display("Start " + Date.now());
      later().then(function() {
        display("Done1 " + Date.now());
      }).then(function() {
        display("Done2 " + Date.now());
      });

      function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = String(msg);
        document.body.appendChild(p);
      }
    })();
  </script>
</body>
</html>


आपका जवाब रद्द करने के लिए संभाल नहीं है
अलेक्जेंडर Danilov

@AlexanderDanilov: वादे रद्द करने योग्य नहीं हैं। आप निश्चित रूप से एक फ़ंक्शन लिख सकते हैं जो किसी ऑब्जेक्ट को रद्द करने की विधि के साथ लौटाता है और, अलग से, वादे के लिए एक एक्सेसर, फिर उस वादे को अस्वीकार कर देता है यदि रद्द करने की विधि को बुलाया गया ...
TJ Crowder

1
@AlexanderDanilov: मैं आगे गया और एक जोड़ा।
टीजे क्राउडर

0

यह मूल प्रश्न का उत्तर नहीं है। लेकिन, जैसा कि एक मूल प्रश्न वास्तविक दुनिया की समस्या नहीं है, यह समस्या नहीं होनी चाहिए। मैंने एक दोस्त को समझाने की कोशिश की कि जावास्क्रिप्ट में वादे क्या हैं और वादे और कॉलबैक के बीच का अंतर।

नीचे दिया गया कोड स्पष्टीकरण के रूप में कार्य करता है:

//very basic callback example using setTimeout
//function a is asynchronous function
//function b used as a callback
function a (callback){
    setTimeout (function(){
       console.log ('using callback:'); 
       let mockResponseData = '{"data": "something for callback"}'; 
       if (callback){
          callback (mockResponseData);
       }
    }, 2000);

} 

function b (dataJson) {
   let dataObject = JSON.parse (dataJson);
   console.log (dataObject.data);   
}

a (b);

//rewriting above code using Promise
//function c is asynchronous function
function c () {
   return new Promise(function (resolve, reject) {
     setTimeout (function(){
       console.log ('using promise:'); 
       let mockResponseData = '{"data": "something for promise"}'; 
       resolve(mockResponseData); 
    }, 2000);      
   }); 

}

c().then (b);

JsFiddle

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