2011-03-15 18 views
26

के लिए ईवेंट श्रोता को एरे में संलग्न करें क्या कोई उपयोगकर्ता यह जानने का कोई तरीका है कि उपयोगकर्ता ने किसी आइटम को एक सरणी पर धक्का दिया है (पुश() के माध्यम से)?जावास्क्रिप्ट: पुश() इवेंट

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

मुझे यह भी मिला जहां मुझे लगता है कि Google ऐसा करता है, लेकिन मुझे कोड समझ में नहीं आता है: एए = फ़ंक्शन (के) { वापसी ऑब्जेक्ट.प्रोटोटाइप [हे] .call (ऑब्जेक्ट (के)) == "[वस्तु सरणी]"

मैं भी एक महान उदाहरण है जो आधार कवर करने लगता है पाया, लेकिन मैं अपने अतिरिक्त धक्का विधि सही ढंग से काम करने के लिए नहीं मिल सकता है: http://jsbin.com/ixovi4/4/edit

+0

क्या उपयोगकर्ता इस यूआई को आपके द्वारा प्रदान किए जा रहे यूआई के माध्यम से बनाता है? – joelt

+0

नहीं, यह एक नियमित सरणी होना चाहिए क्योंकि मेरी स्क्रिप्ट अभी तक लोड नहीं हुई है, इसलिए मेरे पास कोई विशेष रैपर ऑब्जेक्ट नहीं है जो वे बना सकते हैं, आदि – KingOfHypocrites

उत्तर

21

केवल समझदार तरीका ऐसा करने के लिए एक वर्ग लिखना है जो एक सरणी के चारों ओर लपेटता है:

function EventedArray(handler) { 
    this.stack = []; 
    this.mutationHandler = handler || function() {}; 
    this.setHandler = function(f) { 
     this.mutationHandler = f; 
    }; 
    this.callHandler = function() { 
     if(typeof this.mutationHandler === 'function') { 
     this.mutationHandler(); 
     } 
    }; 
    this.push = function(obj) { 
     this.stack.push(obj); 
     this.callHandler(); 
    }; 
    this.pop = function() { 
     this.callHandler(); 
     return this.stack.pop(); 
    }; 
    this.getArray = function() { 
     return this.stack; 
    } 
} 

var handler = function() { 
    console.log('something changed'); 
}; 

var arr = new EventedArray(handler); 

//or 

var arr = new EventedArray(); 
arr.setHandler(handler); 


arr.push('something interesting'); //logs 'something changed' 
+0

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

+0

मुझे यह भी मिला जहां मुझे लगता है कि Google ऐसा करता है, लेकिन मुझे कोड समझ में नहीं आता है: एए = फ़ंक्शन (के) { वापसी ऑब्जेक्ट.प्रोटोटाइप [हे] .call (ऑब्जेक्ट (के)) == " [ऑब्जेक्ट ऐरे] " – KingOfHypocrites

+0

या अगर मेरी स्क्रिप्ट लोड हो जाने के बाद नियमित सरणी को मेरे विशेष ऑब्जेक्ट प्रकार में परिवर्तित करने का कोई तरीका था और फिर विशेष ईवेंट हैंडलर संलग्न करें। – KingOfHypocrites

0

untested है, लेकिन मैं कुछ इस तरह काम कर सकता था यह सोचते हैं रहा हूँ:

Array.prototype.push = function(e) { 
    this.push(e); 
    callbackFunction(e); 
} 
+0

असल में शायद नहीं, मैं निर्मित पुश – moe

+0

में विस्तार करने का प्रयास कर रहा था, यह मेरी आवश्यकता के करीब है, लेकिन मुझे आश्चर्य है कि केवल एक विशिष्ट सरणी पर ऐसा करने का कोई तरीका है या यदि मैं किसी भी तरह सरणी की आईडी जान सकता हूं ? मुझे यह कुछ हद तक काम करने के लिए मिला, लेकिन यह सुनिश्चित करने के लिए कि यह एक सरणी है जिसे मैं वास्तव में देखना चाहता हूं: http://jsbin.com/axate5/edit – KingOfHypocrites

+0

मुझे यह भी मिला जहां मुझे लगता है कि Google करता है यह, लेकिन मुझे कोड को काफी समझ में नहीं आता है: एए = फ़ंक्शन (के) { वापसी ऑब्जेक्ट.प्रोटोटाइप [हे] .call (ऑब्जेक्ट (के)) == "[ऑब्जेक्ट ऐरे]" – KingOfHypocrites

13

इस प्रयास करें:

var MyArray = function() { }; 
MyArray.prototype = []; 
MyArray.prototype.push = function() { 
    console.log('push now!'); 
    for(var i = 0; i < arguments.length; i++) { 
     Array.prototype.push.call(this, arguments[i]); 
    } 
}; 

var arr = new MyArray(); 
arr.push(2,3,'test',1); 

आप धक्का देने के बाद या

0

एक बहुत बेहतर तरीका है आगे बढ़ाने से पहले कम से कार्यों को जोड़ सकते हैं इस तथ्य का उपयोग करने के लिए कि उन विधियों सरणी लंबाई संशोधित करें। तरीका है कि का लाभ लेने के काफी सरल है (CoffeeScript):

class app.ArrayModelWrapper extends Array 
    constructor: (arr,chName,path)-> 
    vl = arr.length 
    @.push.apply(@,arr) 
    Object.defineProperty(@,"length",{ 
     get: ->vl 
     set: (newValue)=> 
     console.log("Hello there ;)") 
     vl = newValue 
     vl 
     enumerable: false 
    }) 
3

क्यों नहीं बस कुछ इस तरह करते हैं?

Array.prototype.eventPush = function(item, callback) { 
    this.push(item); 
    callback(this); 
} 

फिर एक हैंडलर परिभाषित करें।

a = [] 
a.eventPush(1, handler); 
a.eventPush(2, handler); 
18

आपको एक 'eventify' समारोह है कि पारित कर दिया में धक्का ओवरराइड करता है इस्तेमाल कर सकते हैं:

handler = function(array) { 
    console.log(array.length) 
} 

तो जगह है कि आप एक विशिष्ट घटना इतनी तरह हैंडलर में गुजर चाहते हो में eventPush का उपयोग सरणी।

var eventify = function(arr, callback) { 
    arr.push = function(e) { 
     Array.prototype.push.call(arr, e); 
     callback(arr); 
    }; 
}; 

निम्नलिखित उदाहरण में, 3 अलर्ट उठाए जाने चाहिए क्योंकि इवेंट हैंडलर (कॉलबैक) घटना के बाद किया जाता है।

var testArr = [1, 2]; 

testArr.push(3); 

eventify(testArr, function(updatedArr) { 
    alert(updatedArr.length); 
}); 

testArr.push(4); 
testArr.push(5); 
testArr.push(6); 
+2

यह एक सही उत्तर है संदर्भ में दिए गए प्रश्न में। –

+1

इस तरह के एक प्रतिभा कोड स्निपेट। धन्यवाद। –

1

यह एक समारोह सभी सरणियों को onPush कहा जाता है, डिफ़ॉल्ट रूप से यह कुछ भी नहीं करना होगा कि वह सामान्य कामकाज सरणियों के साथ हस्तक्षेप नहीं करता है जोड़ देगा।

बस एक व्यक्तिगत सरणी पर onPush ओवरराइड करें।

Array.prototype.oldPush = Array.prototype.push; 
Array.prototype.push = function(obj){ 
    this.onPush(obj); 
    this.oldPush(obj); 
}; 
//Override this method, be default this shouldnt do anything. As an example it will. 
Array.prototype.onPush = function(obj){ 
    alert(obj + 'got pushed'); 
}; 

//Example 
var someArray = []; 

//Overriding 
someArray.onPush = function(obj){ 
    alert('somearray now has a ' + obj + ' in it'); 
}; 

//Testing 
someArray.push('swag'); 

यह अलर्ट 'somearray अब इसमें एक लूट है'

0

आप एक सारिणी पर यह करने के लिए करना चाहते हैं:

var a = []; 

a.push = function(item) { 
    Array.prototype.push.call(this, item); 
    this.onPush(item); 
}; 

a.onPush = function(obj) { 
    // Do your stuff here (ex: alert(this.length);) 
}; 
0

उद्देश्य तुम कोशिश कर सकते डीबगिंग के लिए। और कॉल स्टैक से कॉलिंग फ़ंक्शन को ट्रैक करें।

yourArray.push = function(){debugger;} 
2

मैं मूल सरणी को एक साधारण पर्यवेक्षक इंटरफेस के चारों ओर लपेटूंगा।

function EventedList(list){ 
    this.listbase = list; 
    this.events = []; 
} 

EventedList.prototype.on = function(name, callback){ 
    this.events.push({ 
     name:name, 
     callback:callback 
    }); 
} 

//push to listbase and emit added event 
EventedList.prototype.push = function(item){ 
    this.listbase.push(item); 
    this._emit("added", item) 
} 

EventedList.prototype._emit = function(evtName, data){ 
    this.events.forEach(function(event){ 
     if(evtName === event.name){ 
      event.callback.call(null, data, this.listbase); 
     } 
    }.bind(this)); 
} 

तो मैं इसे एक आधार सरणी

//returns an object interface that lets you observe the array 
    var evtList = new EventedList([]); 

    //attach a listener to the added event 
    evtList.on('added', function(item, list){ 
     console.log("added event called: item = "+ item +", baseArray = "+ list); 
    }) 

    evtList.push(1) //added event called: item = 1, baseArray = 1 
    evtList.push(2) //added event called: item = 2, baseArray = 1,2 
    evtList.push(3) //added event called: item = 3, baseArray = 1,2,3 

आप भी prePush या postPush या जो कुछ भी घटनाओं की तरह अन्य बातों के निरीक्षण करने के लिए पर्यवेक्षक विस्तार कर सकते हैं के साथ का दृष्टांत था आप के रूप में आप बातचीत फेंकना चाहते हैं आंतरिक आधार सरणी के साथ।

1

कभी-कभी आपको कॉलबैक उपलब्ध होने से पहले चीजों को कतार में करने की आवश्यकता होती है। यह उस मुद्दे को हल करता है। किसी भी वस्तु को किसी सरणी में पुश करें। एक बार जब आप इन वस्तुओं का उपभोग करना शुरू कर देते हैं, तो सरणी और कॉलबैक को QueuedCallback() पर पास करें। QueuedCallbackarray.push को आपके कॉलबैक के रूप में अधिभारित करेगा और उसके बाद किसी कतारबद्ध आइटम के माध्यम से चक्र होगा। आइटम को उस सरणी में धक्का देना जारी रखें और उन्हें सीधे आपके कॉलबैक पर अग्रेषित किया जाएगा। सरणी खाली रहेगी।

सभी ब्राउज़रों और आईई 5.5+ के साथ संगत।

var QueuedCallback = function(arr, callback) { 
    arr.push = callback; 
    while (arr.length) callback(arr.shift()); 
}; 

नमूना उपयोग here

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