2015-06-10 7 views
5

मुझे delay या waitjQuery वादे के लिए फ़ंक्शन नहीं मिल रहा है। मैं इतना (Using jQuery.Deferred to avoid nested setTimeout callbacks) पर एक समारोह पाया है:jquery वादों के लिए देरी

function delay(time) { 
    return function() { 
     console.log("Delaying"); 
     var ret = new $.Deferred(); 
     setTimeout(function() { 
      ret.resolve(); 
     }, time); 
     return ret; 
    }; 
} 

और, यह रास्ता नहीं है मैं इसे कैसे उपयोग करें:

run: function() { 
     return $() 
      .promise() 
      .then(function() { 
       console.log("call together"); 
       console.log("call together");  
      }) 
      .then(delay(2000)) 
      .then(function() { 
       console.log("call first"); 
      }) 
      .then(delay(2000)) 
      .then(function() { 
       console.log("call second"); 
      }) 
    } 

मैं वादा या आस्थगित उद्देश्य यह है कि मैं की तरह लिख सकते हैं का विस्तार करना चाहते:

run: function() { 
      return $() 
       .promise() 
       .then(function() { 
        console.log("call together"); 
        console.log("call together");  
       }) 
       .delay(2000) 
       .then(function() { 
        console.log("call first"); 
       }) 
       .delay(2000) 
       .then(function() { 
        console.log("call second"); 
       }) 
     } 
+0

@ guest271314: मैं वास्तव में वादों के लिए समारोह की जरूरत है। प्रभाव के लिए यह समारोह। – user348173

+0

संभावित डुप्लिकेट [क्या JQuery के वादे ऑब्जेक्ट में विधियों को जोड़ना संभव है?] (Http://stackoverflow.com/q/30719454/1048572) (केवल '.catch' के बजाय '.delay' विधि जोड़ें) – Bergi

+0

@ jfriend00: बिलकुल ठीक है [यह संभव है] (http://stackoverflow.com/a/30719727/1048572) ... लेकिन प्रोटोटाइप को विस्तारित करने के रूप में आसानी से नहीं है। – Bergi

उत्तर

3

@Bergi के रूप में कहते हैं jQuery Deferreds/वादे मूलरूप विरासत से लचीला नहीं हैं।

इसके बजाय, मॉडल jQuery द्वारा अपनाया व्यक्ति वादा उदाहरणों वाक्य रचना के साथ बढ़ाया जा करने के लिए अनुमति देने के लिए है:

deferred.promise(target); 
//or, 
promise.promise(target); //(though the documentation doesn't make this clear) 
// where `target` is an "object onto which the promise methods have to be attached" 
// see https://api.jquery.com/deferred.promise/ 

तरीकों में से एक समूह के साथ एक निर्माता को परिभाषित करके, किसी भी jQuery स्थगित या वादा के साथ बढ़ाया जा सकता है सरल वाक्य रचना

.promise(Constructor()) 

मेरी अप्रकाशित में, undocumented jQuery का वादा किया खेल का मैदान, निर्माता $P नाम पर है और jQuery नाम स्थान में रखा है, इसलिए वास्तविक वाक्य रचना मैं का उपयोग करें:

.promise($.$P()) 

आपको लगता है कि के बारे में पता करने की आवश्यकता है, अधिकांश भाग के लिए, यह स्पष्ट रूप से $.$P() कॉल करने के लिए के रूप में खेल का मैदान एक $.when_() विधि है कि एक पहले से ही बढ़ा वादा रिटर्न भी शामिल है आवश्यक नहीं है।

यहाँ एक .delay() विधि प्रदान करने के लिए पर्याप्त के साथ खेल का मैदान के एक संक्षिप्त संस्करण है:

(function($) { 
    /* *********************************** 
    * The $.$P function returns an object 
    * designed to be extended with 
    * promise methods using the syntax : 
    * myDeferred.promise($.$P()) 
    * myPromise.promise($.$P()) 
    * where `myDeferred`/`myPromise` 
    * are jQuery Deferred/Promise objects. 
    * ***********************************/ 

    /* *********************************** 
    * Methods 
    * ***********************************/ 
    $.$P = function() { 
     if (this instanceof $.$P) { 
      return this; 
     } else { 
      return new $.$P(); 
     } 
    }; 
    $.$P.prototype.then_ = function(fa, fb) { 
     /* A promise method that is the same as .then() 
     * but makes these extra methods available 
     * down-chain. 
     */ 
     return this.then(fa||null, fb||null).promise($.$P()); 
    } 
    $.$P.prototype.delay_ = function(ms) { 
     /* A promise method that 
     * introduces a down-chain delay. 
     */ 
     var promise = this; 
     function f(method) { 
      return function() { setTimeout(function(){ method.apply(null,this); }.bind(arguments), ms||0); }; 
     } 
     return $.Deferred(function(dfrd) { 
      promise.then(f(dfrd.resolve), f(dfrd.reject)); 
     }).promise($.$P()); 
    } 

    /* *********************************** 
    * Utility functions 
    * ***********************************/ 
    function consolidate(args) { 
     /* Convert mixed promises/arrays_of_promises to single array. 
     * Called by all the when_() methods below. 
     */ 
     return Array.prototype.slice.apply(args).reduce(function(arr, current) { 
      return arr.concat(current); 
     }, []); 
    } 

    /* *********************************** 
    * This section extends the jQuery namespace 
    * with a "jQuery.when_()" method. 
    * *********************************** 
    */ 
    $.extend({ 
     'when_': function() { 
      return $.when.apply(null, consolidate(arguments)).promise($.$P()).then_(function() { 
       return consolidate(arguments); 
      }); 
     }, 
    }); 
})(jQuery); 

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

  • सभी खेल का मैदान के स्थिर और वादा तरीकों "_" अंडरस्कोर में खत्म हो: प्लेग्राउंड प्रयोग करने के लिए

    जमीन नियम इस प्रकार हैं।

  • स्टेटिक विधियां, उदाहरण के लिए $.when_(), Playgound इंस्टॉल करके उपलब्ध कराई गई हैं।
  • एक वादे श्रृंखला में वादे एक स्थैतिक विधि, जैसे .when_(), या चेनिंग .promise($.$P()) सहित बढ़ाया जाता है।
  • एक वादे श्रृंखला में, एक्सटेंशन .then() के स्थान पर .then_() मानक विधियों के बजाय "..._" विधियों का उपयोग करके उपलब्ध हैं (श्रृंखला के नीचे)।

तो यहाँ है कि यह कैसे उपयोग करने के लिए प्रश्न के लिए आवश्यक देरी लागू करने के लिए है:

jQuery(function($) { 
    var MYNAMESPACE = { 
     run: function (t) { 
      return $.when_() 
      .then_(function() { 
       log("call together"); 
       log("call together");  
      }) 
      .delay_(t) 
      .then_(function() { 
       log("call first"); 
      }) 
      .delay_(t) 
      .then_(function() { 
       log("call second"); 
      }); 
     } 
    } 
}); 

DEMO

डेमो में, बटन के क्लिक हैंडलर कैसे खेल का मैदान के आगे संकेत देता है इस्तेमाल किया जा सकता है। खेल का मैदान के प्रयोग पर

प्रावधानों:

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

और आखिरकार, उपर्युक्त पर विचार करें यदि आप jQuery के साथ देरी को लागू करने के लिए निर्धारित हैं। एक वचन lib का उपयोग करने के लिए यह बहुत आसान है कि पहले से ही .delay() विधि है।

+0

आप वादे के मालिक हैं। धन्यवाद। – user348173

0

संपादित करें, अपडेट किया गया

करने के लिए संपत्ति delay जोड़ने का प्रयास करें

delay: function(t) { 
     return this.then(function() { 
     var args = arguments; 
     return new $.Deferred(function(d) { 
      setTimeout(function() { 
      // return `data`, if any, to next method, e.g., `.then`, in chain 
      d.resolveWith(this, args) 
      }.bind(this), t || 0) 
     }).promise() 
     }) 
    } 

(function($) { 
 
    $.Deferred = function(a) { 
 
    var b = [ 
 
     ["resolve", "done", $.Callbacks("once memory"), "resolved"], 
 
     ["reject", "fail", $.Callbacks("once memory"), "rejected"], 
 
     ["notify", "progress", $.Callbacks("memory")] 
 
     ], 
 
     c = "pending", 
 
     d = { 
 
     delay: function(t) { 
 
      return this.then(function() { 
 
      var args = arguments; 
 
      return new $.Deferred(function(d) { 
 
       setTimeout(function() { 
 
       // return `data`, if any, to next method, e.g., `.then`, in chain 
 
       d.resolveWith(this, args) 
 
       }.bind(this), t || 0) 
 
      }).promise() 
 
      }) 
 
     }, 
 
     state: function() { 
 
      return c 
 
     }, 
 
     always: function() { 
 
      return e.done(arguments).fail(arguments), this 
 
     }, 
 
     then: function() { 
 
      var a = arguments; 
 
      return $.Deferred(function(c) { 
 
      $.each(b, function(b, f) { 
 
       var g = $.isFunction(a[b]) && a[b]; 
 
       e[f[1]](function() { 
 
       var a = g && g.apply(this, arguments); 
 
       a && $.isFunction(a.promise) 
 
       ? a.promise() 
 
        .done(c.resolve) 
 
        .fail(c.reject) 
 
        .progress(c.notify) 
 
       : c[f[0] + "With"](this === d 
 
        ? c.promise() 
 
        : this, g ? [a] : arguments) 
 
       }) 
 
      }), a = null 
 
      }).promise() 
 
     }, 
 
     promise: function(a) { 
 
      return null != a ? $.extend(a, d) : d 
 
     } 
 
     }, 
 
     e = {}; 
 
    return d.pipe = d.then, $.each(b, function(a, f) { 
 
     var g = f[2], 
 
     h = f[3]; 
 
     d[f[1]] = g.add, h && g.add(function() { 
 
     c = h 
 
     }, b[1^a][2].disable, b[2][2].lock), e[f[0]] = function() { 
 
     return e[f[0] + "With"](this === e ? d : this, arguments), this 
 
     }, e[f[0] + "With"] = g.fireWith 
 
    }), d.promise(e), a && a.call(e, e), e 
 
    } 
 

 
}(jQuery)); 
 

 
var p = { 
 
    run: function() { 
 
    return $() 
 
     .promise() 
 
     .then(function() { 
 
     console.log("call together"); 
 
     console.log("call together"); 
 
     // do stuff 
 
     // pass `data` to next `.then` 
 
     return "call first"; 
 
     }) 
 
     .delay(2000) 
 
     .then(function(data) { 
 
     console.log(data); 
 
     }) 
 
     .delay(2000) 
 
     .then(function() { 
 
     console.log("call second"); 
 
     }) 
 
    } 
 
}; 
 

 
p.run();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> 
 
</script>

+0

"डाउनवोट" विवरण? – guest271314

+0

ओपी ने जो कुछ लिखना चाहता है उसकी बहुत विशिष्ट आवश्यकताओं को दिया। आपका उत्तर उस पर अनुपालन नहीं करता है। इमो यह '.then (देरी (2000))' – Bergi

+0

के साथ अपने कामकाजी समाधान से भी बदतर है। मुझे ऐसा लगता है, हां, हालांकि मैं एक अच्छा समाधान होने के लिए एक अलग कार्यान्वयन के साथ पूरी तरह से '$ डिफर्ड 'को प्रतिस्थापित नहीं करूँगा। । और यदि आप 'resolWith' का उपयोग करना चाहते हैं, तो आपको शायद' पहले 'कॉलबैक से मूल' यह 'और' तर्क 'को पास करना चाहिए, न केवल पहले पैरामीटर। – Bergi

0

मेरा समाधान यहां है। मैं $.Deferred(afterBuild) लपेटता हूं और मूल afterBuild लपेटता हूं जो बदले में .promise(obj) विधि लपेटता है, obj को कस्टम delay विधि के साथ दिया गया है। जो window.setTimeout का उपयोग करता है:

नोट: यह केवल done शाखा में देरी करता है।

function extendPromises(extensions) { 
 
    $.Deferred = (function (originalDeferred) { 
 
     return function (afterBuild) { 
 
      var newAfterBuild = function (d) { 
 
       d.promise = (function (originalPromise) { 
 
        return function (obj) { 
 
         return originalPromise.call(this, $.extend(obj, extensions)); 
 
        }; 
 
       })(d.promise); 
 
       if (afterBuild) afterBuild.apply(this, arguments); 
 
       return this; 
 
      }; 
 
      return originalDeferred.call(this, newAfterBuild); 
 
     }; 
 
    })($.Deferred); 
 
} 
 

 
extendPromises({ 
 
    delay: function (delay) { 
 
     return this.then(function (value) { 
 
      var d = $.Deferred(); 
 
      window.setTimeout(function() { 
 
       d.resolve(value); 
 
      }, delay); 
 
      return d.promise(); 
 
     }); 
 
    } 
 
}); 
 

 
// so now I can do: 
 
$.when("hello") 
 
.then(function (value) { $("#log").append(value+"\n"); return value; }) 
 
.delay(1000) 
 
.then(function (value) { $("#log").append(value); return value; });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<textarea id="log" rows=5></textarea>

संबंधित मुद्दे