2015-04-12 3 views
10

मैं es7 शैली async/प्रतीक्षा विधियों के साथ babeljs का उपयोग कर रहा हूँ। मेरे पास एक मुख्य स्क्रिप्ट है जो ऑब्जेक्ट की एक सरणी पर एसिंक विधि को कॉल करेगी जो सभी रिटर्न वादे करती है। मैं उन सभी के लिए प्रतीक्षा करने के लिए Promise.all() का उपयोग करता हूं, हालांकि, इन कार्यों में काफी समय लग सकता है और यदि वे सीमा से अधिक हो जाते हैं तो मैं उन सभी को निरस्त करना चाहता हूं, और कार्य उचित तरीके से संभालता है।एसिंक्रोनस कॉल को रोकने की क्षमता

क्या ऐसी कोई चीज़ पूरी करने के लिए वैसे भी है? वर्तमान में एकमात्र तरीका जिसे मैं सोच सकता हूं वह एक ऐसी प्रक्रिया को जन्म दे रहा है जो इन तरीकों को बुलाए जाने और उनके लिए सभी इंतजार करने का इंतजार कर रहा है, और यदि समय सीमा तक पहुंच जाती है, तो यह प्रक्रिया को मार सकती है और जो भी इसे संभालने की ज़रूरत होती है।

अद्यतन: मुख्य स्क्रिप्ट का इंतजार कर रहे इन तरीकों के बारे में कुछ स्पष्टीकरण ... वे लंबे समय तक संचालन (बाहरी सिस्टम को कॉल करना, फ़ाइलों को स्ट्रीम करना आदि) कर रहे हैं और एक भी क्रिया नहीं कर सकते स्वतंत्र रूप से रद्द कर दिया।

# अद्यतन 2: कुछ अपरीक्षित अर्द्ध छद्म कोड

class Foo1 { 
    async doSomething() { 
     // call some external system 
     // copy some files 
     // put those files somewhere else (s3) 
    } 
} 
class Foo2 { 
    async doSomething() { 
     // Do some long computations 
     // Update some systems 
    } 
} 

class FooHandler { 
    constructor() { 
     this.fooList = []; 
    } 

    async start() { 
     await Promise.all(this.fooList.map(async (foo) => { 
      return await foo.doSomething(); 
     })); 
    } 
} 

let handler = new FooHandler(); 

handler.fooList.push(new Foo1()); 
handler.fooList.push(new Foo2()); 

// if this call takes too long because of slow connections, errors, whatever, 
// abort start(), handle it in whatever meaningful way, and continue on. 
await handler.start(); 
+1

क्या आप अपना कोड पोस्ट कर सकते हैं? –

+1

यह वास्तविक समस्या के बारे में एक उत्कृष्ट सवाल है, यह क्यों कम हो गया है? –

+0

संबंधित: [EMCAScript6 (वेनिला जावास्क्रिप्ट) वादा श्रृंखला को कैसे रद्द करें] (http://stackoverflow.com/q/29478751/1048572) – Bergi

उत्तर

7

मूल निवासी ES6 वर्तमान में वादा किया सीधे रद्द समर्थन नहीं करते। कई जगहों पर हर समय इसके बारे में बातचीत होती है लेकिन यह अभी तक नहीं है।

चूंकि देशी वादे इसका समर्थन नहीं करते हैं और एसिंक/वादे पर कामों का इंतजार करते हैं, वर्तमान में इसे निरस्त करने के लिए आसान तरीके से निर्मित नहीं किया गया है। वादा वापस करने की कार्रवाई करते समय एक आम तरीका टोकन का उपयोग करना है।

मान लीजिए कि आप promisified एक्सएचआर प्राप्त की है:

// simplification 
function ajax(url){ 
    return new Promise((resolve, reject) => { 
     let xhr = new XMLHttpRequest; 
     xhr.open("GET", url); 
     xhr.onload =() => resolve(xhr.responseText); 
     xhr.onerror = reject; 
     xhr.send(); 
    }); 
} 

अब आप उपयोग करना चाहते हैं:

async function foo(){ 
    let result = await ajax("/myApi"); 
    let result2 = await ajax("/myApi2?token=" + result); 
} 

अब मान लें कि हम कुछ मामलों में AJAX रद्द करना चाहते हैं, हम कर सकते हैं जैसे एक टोकन पारित:

function ajax(url, token = {}){ 
    return new Promise((resolve, reject) => { 
     let xhr = new XMLHttpRequest; 
     xhr.open("GET", url); 
     Object(token).cancel =() => { xhr.abort(), reject(); }; 
     xhr.onload =() => resolve(xhr.responseText); 
     xhr.onerror = reject; 
     xhr.send(); 
    }); 
} 

यह आपको करते हैं जाएगा:

async function foo(){ 
    let token = {}; 
    let req = ajax("/myApi", token); // note no await 
    // now let's say we want to abort the request since we don't 
    // need the data 
    token.cancel(); // this will abort the token 
} 

इस दृष्टिकोण को चेनिंग के साथ काम करने की ज़रूरत है, सौभाग्य से ES6 वाक्यविन्यास के साथ यह सौदा के रूप में बड़ा नहीं है। शुभकामनाएं और खुश कोडिंग।

+0

धन्यवाद, यह अच्छी जानकारी है। हालांकि ये एसिंक विधियां बहुत अधिक काम कर सकती हैं (एक स्थान से दूसरे स्थान पर एक फ़ाइल कॉपी करें, कुछ बाहरी कॉल करें, फिर डेटा को कहीं भी स्ट्रीम करें (जैसे एस 3 पर पोस्ट करना) और फिर कुछ साफ काम करें)। दुर्भाग्य से यह एक भी कॉल नहीं है कि ये विधियां कर रही हैं। –

+0

तो टोकन को समेकित करें। –

0

यह वास्तव में आपके द्वारा उपयोग की जाने वाली API पर निर्भर करता है। नोड के मौजूदा एसिंक एपीआई विधियों में से अधिकांश आसानी से "इंटरप्टिबल" (readfileasync और पसंद नहीं) हैं, जब तक कि आप स्वयं का अपना कार्यान्वयन नहीं करते हैं।

अनुसूचित प्रेषण को आसानी से रद्द करने का कोई आसान तरीका नहीं है। अब तक एपीआई इस बात के साथ दिमाग में नहीं बनाया गया है। वादे भी मदद नहीं कर सकते हैं जब एपीआई के निम्न स्तर के कार्यान्वयन निरस्त करने का समर्थन नहीं करते हैं।

लेकिन कुछ एपीआई में आप data घटनाओं और "अगले टिक" कार्यान्वयन पर धाराओं जैसे "चरणों" को रोकते हैं। वहां आप आगे की प्रक्रिया को रोक सकते हैं। (धाराएं वास्तव में अवरोध-सक्षम आईओ सामग्री को कार्यान्वित करने के लिए बहुत अच्छे उम्मीदवार हैं)

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

var do_fibonacci_async = function(a,limiter,callback){ 
    if(limiter.halt){ 
     callback(limiter.msg); 
    } 
    else if(a <= 2){ 
     callback(limiter.halt ? limiter.msg : 1); 
    }else{ 
     process.nextTick(function(){ 
      do_fibonacci_async(a - 1,limiter, function(val1){ 
       do_fibonacci_async(a - 2,limiter, function(val2){ 
        callback(limiter.halt ? limiter.msg : val1+val2); 
       }); 
      }); 
     }); 
    } 
} 

exports.fibonacci_async = function(a,callback){ 
      if(!a || isNaN(a)){ 
     callback(new out("fibonacci", [], "")); 
     return; 
    } 

    var limiter = {halt:false, msg:"Too large to compute"}; 
    setTimeout(function(){ 
     limiter.halt = true; 
    },5000); 

    do_fibonacci_async(a,limiter,function(val){ 
     callback(new out("fibonacci", [a], val)); 
    }); 
} 
1

(जिसमें प्रकार वैकल्पिक हैं और ES6 और कुछ ES7 सुविधाओं बॉक्स से बाहर समर्थित हैं) बेबेल के बजाय और ब्लूबर्ड वादे का उपयोग करें, आप जिस रद्दीकरण सेमेन्टिक्स की तलाश में हैं, उसे हासिल किया जा सकता है। https://www.npmjs.com/package/cancelable-awaiter

इसके साथ

आप promise.cancel() और promise.finally() जो Bluebird आप देता है के साथ संयोजन के रूप में aync/इंतजार सिंटैक्स का उपयोग कर सकते हैं:

मैं एक साधारण मॉड्यूल जो एक है कि Bluebird रद्दीकरण का समर्थन करता है के साथ डिफ़ॉल्ट टाइपप्रति __awaiter सहायक की जगह बना लिया है।

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