एक वैनिला ECMAScript 6 वादा श्रृंखला रद्द करें


110

.thenजावास्क्रिप्ट Promiseउदाहरण के समाशोधन के लिए कोई विधि है ?

मैंने क्विंट के शीर्ष पर जावास्क्रिप्ट परीक्षण रूपरेखा लिखी है । फ्रेमवर्क एक-एक करके सभी को एक-एक करके चलाता है Promise। (इस कोड ब्लॉक की लंबाई के लिए खेद है। मैंने इसे सर्वश्रेष्ठ के रूप में टिप्पणी की, इसलिए यह कम थकाऊ लगता है।)

/* Promise extension -- used for easily making an async step with a
       timeout without the Promise knowing anything about the function 
       it's waiting on */
$$.extend(Promise, {
    asyncTimeout: function (timeToLive, errorMessage) {
        var error = new Error(errorMessage || "Operation timed out.");
        var res, // resolve()
            rej, // reject()
            t,   // timeout instance
            rst, // reset timeout function
            p,   // the promise instance
            at;  // the returned asyncTimeout instance

        function createTimeout(reject, tempTtl) {
            return setTimeout(function () {
                // triggers a timeout event on the asyncTimeout object so that,
                // if we want, we can do stuff outside of a .catch() block
                // (may not be needed?)
                $$(at).trigger("timeout");

                reject(error);
            }, tempTtl || timeToLive);
        }

        p = new Promise(function (resolve, reject) {
            if (timeToLive != -1) {
                t = createTimeout(reject);

                // reset function -- allows a one-time timeout different
                //    from the one original specified
                rst = function (tempTtl) {
                    clearTimeout(t);
                    t = createTimeout(reject, tempTtl);
                }
            } else {
                // timeToLive = -1 -- allow this promise to run indefinitely
                // used while debugging
                t = 0;
                rst = function () { return; };
            }

            res = function () {
                clearTimeout(t);
                resolve();
            };

            rej = reject;
        });

        return at = {
            promise: p,
            resolve: res,
            reject: rej,
            reset: rst,
            timeout: t
        };
    }
});

/* framework module members... */

test: function (name, fn, options) {
    var mod = this; // local reference to framework module since promises
                    // run code under the window object

    var defaultOptions = {
        // default max running time is 5 seconds
        timeout: 5000
    }

    options = $$.extend({}, defaultOptions, options);

    // remove timeout when debugging is enabled
    options.timeout = mod.debugging ? -1 : options.timeout;

    // call to QUnit.test()
    test(name, function (assert) {
        // tell QUnit this is an async test so it doesn't run other tests
        // until done() is called
        var done = assert.async();
        return new Promise(function (resolve, reject) {
            console.log("Beginning: " + name);

            var at = Promise.asyncTimeout(options.timeout, "Test timed out.");
            $$(at).one("timeout", function () {
                // assert.fail() is just an extension I made that literally calls
                // assert.ok(false, msg);
                assert.fail("Test timed out");
            });

            // run test function
            var result = fn.call(mod, assert, at.reset);

            // if the test returns a Promise, resolve it before resolving the test promise
            if (result && result.constructor === Promise) {
                // catch unhandled errors thrown by the test so future tests will run
                result.catch(function (error) {
                    var msg = "Unhandled error occurred."
                    if (error) {
                        msg = error.message + "\n" + error.stack;
                    }

                    assert.fail(msg);
                }).then(function () {
                    // resolve the timeout Promise
                    at.resolve();
                    resolve();
                });
            } else {
                // if test does not return a Promise, simply clear the timeout
                // and resolve our test Promise
                at.resolve();
                resolve();
            }
        }).then(function () {
            // tell QUnit that the test is over so that it can clean up and start the next test
            done();
            console.log("Ending: " + name);
        });
    });
}

यदि कोई परीक्षण समय समाप्त हो जाता है, तो मेरा टाइमआउट वादा assert.fail()परीक्षण पर होगा , ताकि परीक्षण विफल के रूप में चिह्नित हो, जो सभी अच्छी तरह से और अच्छा है, लेकिन परीक्षण जारी है क्योंकि परीक्षण का वादा ( result) अभी भी इसे हल करने के लिए इंतजार कर रहा है।

मुझे अपना टेस्ट रद्द करने के लिए एक अच्छे तरीके की जरूरत है। मैं इसे फ्रेमवर्क मॉड्यूल this.cancelTestया कुछ पर एक फ़ील्ड बनाकर कर सकता हूं , और हर बार जांच कर सकता हूं (उदाहरण के लिए प्रत्येक then()पुनरावृत्ति की शुरुआत में ) कि क्या रद्द करना है। हालाँकि, आदर्श रूप से, मैं अपने चर पर $$(at).on("timeout", /* something here */)शेष then()s को साफ़ करने के लिए उपयोग कर सकता हूं result, ताकि बाकी परीक्षण में से कोई भी न चले।

क्या ऐसा कुछ मौजूद है?

शीघ्र नवीनीकरण

मैंने प्रयोग करने की कोशिश की Promise.race([result, at.promise])। यह काम नहीं किया।

अद्यतन 2 + भ्रम

मुझे अनवरोधित करने के लिए, मैंने mod.cancelTestपरीक्षण विचार के भीतर / मतदान के साथ कुछ पंक्तियाँ जोड़ीं। (मैंने इवेंट ट्रिगर भी हटा दिया है।)

return new Promise(function (resolve, reject) {
    console.log("Beginning: " + name);

    var at = Promise.asyncTimeout(options.timeout, "Test timed out.");
    at.promise.catch(function () {
        // end the test if it times out
        mod.cancelTest = true;
        assert.fail("Test timed out");
        resolve();
    });

    // ...
    
}).then(function () {
    // tell QUnit that the test is over so that it can clean up and start the next test
    done();
    console.log("Ending: " + name);
});

मैंने catchबयान में एक विराम बिंदु निर्धारित किया है , और यह हिट हो रहा है। अब जो मुझे भ्रमित कर रहा है वह यह है कि then()बयान को नहीं बुलाया जा रहा है। विचार?

अपडेट ३

आखिरी बात का पता लगाया। fn.call()एक त्रुटि फेंक रहा था जिसे मैंने नहीं पकड़ा, इसलिए परीक्षण का वादा at.promise.catch()इसे हल करने से पहले अस्वीकार कर रहा था ।


ES6 वादों के साथ रद्दीकरण करना संभव है, लेकिन यह वादे की संपत्ति नहीं है (बल्कि - यह उस फ़ंक्शन का गुण है जो इसे वापस करता है) यदि आप रुचि रखते हैं तो मैं एक छोटा उदाहरण बना सकता हूं।
बेंजामिन ग्रुएनबाम 16

@BenjaminGruenbaum मुझे पता है कि यह लगभग एक साल हो गया है, लेकिन मुझे अभी भी दिलचस्पी है अगर आपके पास एक उदाहरण लिखने का समय है। :)
dx_over_dt

1
यह एक साल पहले की बात है, लेकिन इसे रद्द करने के टोकन और रद्द करने के वादे के साथ आधिकारिक तौर पर कल दो दिन पहले चर्चा की गई है। चरण 1
बेंजामिन ग्रुएनबाम

3
एक वादा रद्द करने के लिए ES6 का उत्तर अवलोकनीय है। इसके बारे में आप यहाँ और अधिक पढ़ सकते हैं: github.com/Reactive-Extensions/RxJS
फ्रैंक गोअर्टानी

वादा रद्द करने के लिए पुस्तकालय का उपयोग करने पर मेरे जवाब को जोड़ना Prex
noseratio

जवाबों:


75

क्या .thenएक जावास्क्रिप्ट वादा उदाहरण के एस को साफ करने के लिए एक विधि है ?

कम से कम ECMAScript 6 में नहीं। वादे (और उनके thenहैंडलर्स) डिफ़ॉल्ट रूप से अकारण होते हैं (दुर्भाग्य से) । इसे सही तरीके से कैसे किया जाए, इस बारे में ईएस-चर्चा (जैसे यहां ) पर थोड़ी चर्चा है , लेकिन जो भी दृष्टिकोण जीतेगा वह ईएस 6 में नहीं उतरेगा।

वर्तमान दृष्टिकोण यह है कि उपवर्ग अपने स्वयं के कार्यान्वयन का उपयोग करके रद्द करने योग्य वादों को बनाने की अनुमति देगा (यह सुनिश्चित नहीं है कि यह कितना अच्छा काम करेगा)

जब तक भाषा कमेटी ने सबसे अच्छा तरीका निकाला है (ईएस 7 उम्मीद है?) तब भी आप उपयोगकर्तालैंड प्रॉमिस कार्यान्वयन का उपयोग कर सकते हैं, जिनमें से कई फीचर रद्द हो सकते हैं।

वर्तमान चर्चा https://github.com/domenic/cancelable-promise और https://github.com/bergus/promise-cancellation ड्राफ्ट में है।


2
"थोड़ी चर्चा" - मैं शायद 30 धागे esdiscuss या GitHub पर लिंक कर सकता हूं :) (ब्लूबर्ड 3.0 में रद्द करने के साथ अपनी खुद की मदद का उल्लेख नहीं करने के लिए)
बेंजामिन ग्रुएनबाउम

@BenjaminGruenbaum: क्या आपके पास वो लिंक कहीं साझा करने के लिए तैयार हैं? मैं लंबे समय से राय और प्रयासों को संक्षेप में प्रस्तुत करना चाहता था और एस्किस्कस के लिए एक प्रस्ताव पोस्ट करना चाहता था, इसलिए मुझे खुशी होगी अगर मैं वापस जांच कर सकता हूं कि मैं कुछ भी नहीं भूल गया।
बर्गी

मैंने उन्हें काम पर रखा है - इसलिए मैं उन्हें 3-4 दिनों में दे दूंगा। आप एक अच्छी शुरुआत के लिए वादों-अधिशेष के तहत वादा रद्द करने की कल्पना की जांच कर सकते हैं।
बेंजामिन ग्रुएनबाम 18

1
@ LUH3417: "सामान्य" कार्य उस संबंध में उबाऊ हैं। आप एक कार्यक्रम शुरू करते हैं और तब तक इंतजार करते हैं जब तक कि यह समाप्त नहीं हो जाता है - या आप killइसे करते हैं और इस बात की अनदेखी करते हैं कि संभावित रूप से अजीब स्थिति में आपके वातावरण में क्या प्रभाव छोड़ दिया है (इसलिए आप आमतौर पर सिर्फ उतना ही फेंक देते हैं, जैसे कि कोई भी आधा-तैयार आउटपुट)। गैर-अवरुद्ध या अतुल्यकालिक कार्यों को हालांकि इंटरेक्टिव अनुप्रयोगों में काम करने के लिए बनाया गया है, जहां आप चल रहे कार्यों के निष्पादन पर इस तरह के महीन नियंत्रण रखना चाहते हैं।
Bergi


50

जबकि ईएस 6 में ऐसा करने का कोई मानक तरीका नहीं है, लेकिन इसे संभालने के लिए ब्लूबर्ड नामक एक पुस्तकालय है ।

प्रतिक्रिया प्रलेखन के भाग के रूप में वर्णित एक अनुशंसित तरीका भी है। यह आपके 2 और 3 अपडेट में आपके जैसा दिखता है।

const makeCancelable = (promise) => {
  let hasCanceled_ = false;

  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then((val) =>
      hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
    );
    promise.catch((error) =>
      hasCanceled_ ? reject({isCanceled: true}) : reject(error)
    );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled_ = true;
    },
  };
};

const cancelablePromise = makeCancelable(
  new Promise(r => component.setState({...}}))
);

cancelablePromise
  .promise
  .then(() => console.log('resolved'))
  .catch((reason) => console.log('isCanceled', reason.isCanceled));

cancelablePromise.cancel(); // Cancel the promise

से लिया गया: https://facebook.github.io/react/blog/2015/12/16/ismounted-shaipatpat.html


1
रद्द की यह परिभाषा सिर्फ वादे को खारिज कर रही है। यह "रद्द" की परिभाषा पर निर्भर करता है।
अलेक्जेंडर मिल्स

1
और अगर आप वादों का एक सेट रद्द करना चाहते हैं तो क्या होगा?
मैथ्यू ब्रूचर

1
इस दृष्टिकोण के साथ समस्या यह है कि यदि आपके पास एक वादा है जो कभी भी हल नहीं करेगा या इसे अस्वीकार नहीं करेगा।
DaNeSh

2
यह आंशिक रूप से सही है, लेकिन यदि आपके पास लंबे समय से वादा करने वाली श्रृंखला है, तो यह दृष्टिकोण काम नहीं करेगा।
वीकोको कारसिकको

11

मैं वास्तव में हैरान हूं कि कोई भी इसके Promise.raceलिए एक उम्मीदवार के रूप में उल्लेख नहीं करता है:

const actualPromise = new Promise((resolve, reject) => { setTimeout(resolve, 10000) });
let cancel;
const cancelPromise = new Promise((resolve, reject) => {
    cancel = reject.bind(null, { canceled: true })
})

const cancelablePromise = Object.assign(Promise.race([actualPromise, cancelPromise]), { cancel });

3
मुझे विश्वास नहीं है कि यह काम करता है। यदि आप लॉग इन करने के वादे को बदलते हैं, तो चलने के बाद cancel()भी लॉग को कॉल किया जाएगा। `` `वास्तविक वास्तविक समय = नया वादा ((समाधान, अस्वीकार) => {सेटटाइमआउट () => {कंसोल.लॉग ('वास्तविक कहा जाता है'); समाधान ()}, 10000)}); `` `
शंक

2
सवाल यह था कि किसी वादे को रद्द कैसे किया जाए (=> रोकें जाने के लिए जंजीर thenको रोकें ), न कि कैसे रद्द किया जाए setTimeout(=> clearTimeout) या सिंक्रोनस कोड, जहां तक ​​कि यदि आप प्रत्येक पंक्ति के बाद (यदि if (canceled) return) यह हासिल नहीं किया जा सकता है। (ऐसा न करें)
Pho3nixHun

10
const makeCancelable = promise => {
    let rejectFn;

    const wrappedPromise = new Promise((resolve, reject) => {
        rejectFn = reject;

        Promise.resolve(promise)
            .then(resolve)
            .catch(reject);
    });

    wrappedPromise.cancel = () => {
        rejectFn({ canceled: true });
    };

    return wrappedPromise;
};

उपयोग:

const cancelablePromise = makeCancelable(myPromise);
// ...
cancelablePromise.cancel();

5

वादे के क्रियान्वयन को रोकना वास्तव में असंभव है, लेकिन आप इसे अस्वीकार कर सकते हैं और इसे वादे से ही बुला सकते हैं।

class CancelablePromise {
  constructor(executor) {
    let _reject = null;
    const cancelablePromise = new Promise((resolve, reject) => {
      _reject = reject;
      return executor(resolve, reject);
    });
    cancelablePromise.cancel = _reject;

    return cancelablePromise;
  }
}

उपयोग:

const p = new CancelablePromise((resolve, reject) => {
  setTimeout(() => {
    console.log('resolved!');
    resolve();
  }, 2000);
})

p.catch(console.log);

setTimeout(() => {
  p.cancel(new Error('Messed up!'));
}, 1000);

1
@dx_over_dt आपका संपादन एक शानदार टिप्पणी होगी, लेकिन संपादन नहीं। कृपया ओपी के दायरे में (जब तक कि पोस्ट को सामुदायिक विकी के रूप में चिह्नित नहीं किया जाता है) ऐसे मूल संपादन छोड़ दें।
टाइलर

@ टाइलेरह टाइपिंग और लाइक को ठीक करने के लिए संपादन का बिंदु है? या जानकारी के अद्यतन के रूप में यह पुराना हो जाता है? मैं अन्य लोगों के पदों को संपादित करने की क्षमता के लिए नया हूं।
dx_over_dt

@dx_over_dt हां, संपादन टाइपोस, व्याकरण संबंधी त्रुटियों को ठीक करके और वाक्यविन्यास हाइलाइटिंग जोड़कर पदों में सुधार करना है (यदि कोई व्यक्ति कोड का एक गुच्छा पोस्ट करता है लेकिन उदाहरण के लिए इसे `` के साथ इंडेंट या टैग नहीं करता है)। चीजों के लिए अतिरिक्त स्पष्टीकरण या तर्क / औचित्य जैसी मूल सामग्री को जोड़ना आमतौर पर उस व्यक्ति का उद्देश्य होता है जिसने उत्तर पोस्ट किया है। आप इसे टिप्पणियों में सुझाने के लिए स्वतंत्र हैं, और ओपी को टिप्पणी के बारे में सूचित किया जाएगा और फिर इसका जवाब दे सकते हैं, या वे आपके सुझाव को स्वयं पोस्ट में शामिल कर सकते हैं।
TylerH

@dx_over_dt अपवाद हैं यदि किसी पोस्ट को "सामुदायिक विकी" के रूप में चिह्नित किया जाता है, तो यह दर्शाता है कि यह एक सहयोगी पद (जैसे विकिपीडिया) के रूप में सेवा करने का इरादा है, या यदि पोस्ट के साथ गंभीर मुद्दे हैं जैसे असभ्य / अपमानजनक भाषा, खतरनाक / हानिकारक सामग्री ( जैसे सुझाव या कोड जो आपको वायरस देने या आपको गिरफ्तार करने आदि के लिए उत्तरदायी हैं), या व्यक्तिगत जानकारी जैसे स्वास्थ्य रिकॉर्ड, फ़ोन नंबर, क्रेडिट कार्ड, आदि; अपने आप को दूर करने के लिए स्वतंत्र महसूस करें।
टाइलेर

यह ध्यान देने योग्य है कि वादे के भीतर निष्पादन को रोका नहीं जा सकता है क्योंकि जावास्क्रिप्ट एकल-थ्रेडेड है। जबकि वादा फ़ंक्शन निष्पादित किया जा रहा है, और कुछ नहीं चल रहा है, इसलिए निष्पादन को रोकना ट्रिगर करने के लिए कुछ भी नहीं है।
dx_over_dt


2

यहां हमारा कार्यान्वयन https://github.com/permettez-moi-de-construire/cancellable-promise है

जैसे इस्तेमाल किया

const {
  cancellablePromise,
  CancelToken,
  CancelError
} = require('@permettezmoideconstruire/cancellable-promise')

const cancelToken = new CancelToken()

const initialPromise = SOMETHING_ASYNC()
const wrappedPromise = cancellablePromise(initialPromise, cancelToken)


// Somewhere, cancel the promise...
cancelToken.cancel()


//Then catch it
wrappedPromise
.then((res) => {
  //Actual, usual fulfill
})
.catch((err) => {
  if(err instanceOf CancelError) {
    //Handle cancel error
  }

  //Handle actual, usual error
})

कौन कौन से :

  • प्रॉमिस एपीआई को स्पर्श न करें
  • हमें catchकॉल के अंदर और रद्द करना चाहिए
  • रद्द करने पर भरोसा किया जा रहा अस्वीकार कर के बजाय का समाधान किसी अन्य प्रस्ताव या कार्यान्वयन के विपरीत

खींचने और टिप्पणियों का स्वागत करते हैं


2

की मदद से वादा रद्द किया जा सकता है AbortController

क्या तब साफ़ करने की कोई विधि है: हाँ आप AbortControllerवस्तु के साथ वादे को अस्वीकार कर सकते हैं और फिर promiseवसीयत सभी ब्लॉक को बायपास कर सीधे कैच ब्लॉक में चला जाएगा।

उदाहरण:

import "abortcontroller-polyfill";

let controller = new window.AbortController();
let signal = controller.signal;
let elem = document.querySelector("#status")

let example = (signal) => {
    return new Promise((resolve, reject) => {
        let timeout = setTimeout(() => {
            elem.textContent = "Promise resolved";
            resolve("resolved")
        }, 2000);

        signal.addEventListener('abort', () => {
            elem.textContent = "Promise rejected";
            clearInterval(timeout);
            reject("Promise aborted")
        });
    });
}

function cancelPromise() {
    controller.abort()
    console.log(controller);
}

example(signal)
    .then(data => {
        console.log(data);
    })
    .catch(error => {
        console.log("Catch: ", error)
    });

document.getElementById('abort-btn').addEventListener('click', cancelPromise);

एचटीएमएल


    <button type="button" id="abort-btn" onclick="abort()">Abort</button>
    <div id="status"> </div>

नोट: सभी ब्राउज़र में समर्थित नहीं, पॉलीफ़िल जोड़ने की आवश्यकता है।

लाइव उदाहरण

सुरुचिपूर्ण-झील -5jnh3 संपादित करें


1

सरल संस्करण :

बस अस्वीकार समारोह बाहर दे।

function Sleep(ms,cancel_holder) {

 return new Promise(function(resolve,reject){
  var done=false; 
  var t=setTimeout(function(){if(done)return;done=true;resolve();}, ms);
  cancel_holder.cancel=function(){if(done)return;done=true;if(t)clearTimeout(t);reject();} 
 })
}

एक आवरण समाधान (कारखाना)

मुझे जो समाधान मिला वह एक रद्द करने वाली वस्तु है। यह एक रद्द समारोह होगा। यदि यह एक रद्द समारोह है तो यह रद्द करने योग्य है।

यह रद्द फ़ंक्शन त्रुटि ('रद्द') के साथ वादे को अस्वीकार करता है।

समाधान से पहले, अस्वीकार या on_cancel बिना कारण के रद्द किए जाने वाले फ़ंक्शन को रोकें।

मैंने इंजेक्शन द्वारा रद्द कार्रवाई को पारित करने के लिए सुविधाजनक पाया है

function cancelablePromise(cancel_holder,promise_fn,optional_external_cancel) {
  if(!cancel_holder)cancel_holder={};
  return new Promise( function(resolve,reject) {
    var canceled=false;
    var resolve2=function(){ if(canceled) return; canceled=true; delete cancel_holder.cancel; resolve.apply(this,arguments);}
    var reject2=function(){ if(canceled) return; canceled=true; delete cancel_holder.cancel; reject.apply(this,arguments);}
    var on_cancel={}
    cancel_holder.cancel=function(){
      if(canceled) return; canceled=true;

      delete cancel_holder.cancel;
      cancel_holder.canceled=true;

      if(on_cancel.cancel)on_cancel.cancel();
      if(optional_external_cancel)optional_external_cancel();

      reject(new Error('canceled'));
    };

    return promise_fn.call(this,resolve2,reject2,on_cancel);        
  });
}

function Sleep(ms,cancel_holder) {

 return cancelablePromise(cancel_holder,function(resolve,reject,oncacnel){

  var t=setTimeout(resolve, ms);
  oncacnel.cancel=function(){if(t)clearTimeout(t);}     

 })
}


let cancel_holder={};

// meanwhile in another place it can be canceled
setTimeout(function(){  if(cancel_holder.cancel)cancel_holder.cancel(); },500) 

Sleep(1000,cancel_holder).then(function() {
 console.log('sleept well');
}, function(e) {
 if(e.message!=='canceled') throw e;
 console.log('sleep interrupted')
})

1

वादा-निरर्थक प्रयास करें : https://www.npmjs.com/package/promise-abortable

$ npm install promise-abortable
import AbortablePromise from "promise-abortable";

const timeout = new AbortablePromise((resolve, reject, signal) => {
  setTimeout(reject, timeToLive, error);
  signal.onabort = resolve;
});

Promise.resolve(fn()).then(() => {
  timeout.abort();
});

1

यदि आपका कोड एक कक्षा में रखा गया है तो आप उसके लिए एक डेकोरेटर का उपयोग कर सकते हैं। आप बर्तन-सज्जाकार ( npm install --save utils-decorators) में इस तरह के डेकोरेटर हैं । यह सजाए गए तरीके के पिछले आह्वान को रद्द कर देगा यदि पिछली कॉल के समाधान से पहले उस विशिष्ट विधि के लिए एक और कॉल किया गया था।

import {cancelPrevious} from 'utils-decorators';

class SomeService {

   @cancelPrevious()
   doSomeAsync(): Promise<any> {
    ....
   }
}

https://github.com/vlio20/utils-decorators#cancelprevious-method


0

यदि आप सभी थेन / कैच को रोकना चाहते हैं तो निष्पादित होने से आप ऐसा वादा कर सकते हैं जो कभी हल नहीं होगा। इसमें संभवतः मेमोरी लीक प्रतिकार है, लेकिन यह समस्या को ठीक कर देगा और अधिकांश अनुप्रयोगों में बहुत अधिक बर्बाद स्मृति का कारण नहीं होना चाहिए।

new Promise((resolve, reject) => {
    console.log('first chain link executed')
    resolve('daniel');
}).then(name => {
    console.log('second chain link executed')
    if (name === 'daniel') {
        // I don't want to continue the chain, return a new promise
        // that never calls its resolve function
        return new Promise((resolve, reject) => {
            console.log('unresolved promise executed')
        });
    }
}).then(() => console.log('last chain link executed'))

// VM492:2 first chain link executed
// VM492:5 second chain link executed
// VM492:8 unresolved promise executed

0

संकेत then()देने के catch()लिए और जल्दी बाहर निकलने के लिए "रद्द" संपत्ति सेट करें । यह बहुत प्रभावी है, विशेष रूप से वेब वर्कर्स में जो मौजूदा माइक्रोट्स्क हैं जो कि onmessageहैंडलर से प्रॉमिस में कतारबद्ध हैं ।

// Queue task to resolve Promise after the end of this script
const promise = new Promise(resolve => setTimeout(resolve))

promise.then(_ => {
  if (promise.canceled) {
    log('Promise cancelled.  Exiting early...');
    return;
  }

  log('No cancelation signaled.  Continue...');
})

promise.canceled = true;

function log(msg) {
  document.body.innerHTML = msg;
}


0

मेरे लिए @Michael Yagudaev का जवाब काम करता है।

लेकिन मूल उत्तर ने रिजेक्ट हैंडलिंग को संभालने के लिए .catch () के साथ लिपटे वादे को श्रृंखलाबद्ध नहीं किया, यहाँ @Michael Yagudaev के उत्तर के शीर्ष पर मेरा सुधार है:

const makeCancelablePromise = promise => {
  let hasCanceled = false;
  const wrappedPromise = new Promise((resolve, reject) => {
    promise
      .then(val => (hasCanceled ? reject({ isCanceled: true }) : resolve(val)))
      .catch(
        error => (hasCanceled ? reject({ isCanceled: true }) : reject(error))
      );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled = true;
    }
  };
};

// Example Usage:
const cancelablePromise = makeCancelable(
  new Promise((rs, rj) => {
    /*do something*/
  })
);
cancelablePromise.promise.then(() => console.log('resolved')).catch(err => {
  if (err.isCanceled) {
    console.log('Wrapped promise canceled');
    return;
  }
  console.log('Promise was not canceled but rejected due to errors: ', err);
});
cancelablePromise.cancel();

0

यदि पी एक चर है जिसमें एक वादा है, तो p.then(empty);यह वादा पूरा होने पर खारिज कर देना चाहिए या यदि यह पहले से ही पूरा हो गया है (हाँ, मुझे पता है कि यह मूल प्रश्न नहीं है, लेकिन यह मेरा सवाल है)। "खाली" है function empty() {}। मैं सिर्फ एक शुरुआत कर रहा हूं और शायद गलत हूं, लेकिन ये अन्य जवाब बहुत जटिल हैं। वादे सरल माने जाते हैं।


0

मैं अभी भी इस विचार के माध्यम से काम कर रहा हूं, लेकिन यहां बताया गया है कि मैंने setTimeoutएक उदाहरण के रूप में रद्द करने योग्य वादा कैसे लागू किया है ।

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

  • सबसे पहले, मुझे लगता है कि एक वादा जल्दी खत्म करने के दो कारण हैं: इसे खत्म करना और इसके साथ (जिसे मैंने संकल्प कहा है ) और रद्द करने के लिए (जिसे मैंने अस्वीकार कहा है )। बेशक, यह सिर्फ मेरी भावना है। बेशक वहाँ एक Promise.resolve()विधि है, लेकिन यह स्वयं निर्माता में है, और एक डमी को हल करने का वादा देता है। यह उदाहरण resolve()विधि वास्तव में एक तात्कालिक वादा वस्तु का समाधान करती है।

  • दूसरा, आप ख़ुशी-ख़ुशी कुछ भी जोड़ सकते हैं जैसे आप इसे वापस करने से पहले एक नए बनाए गए वादे की वस्तु को जोड़ सकते हैं, और इसलिए मैंने इसे आत्म-निहित बनाने के लिए अभी resolve()और जोड़ा है reject()

  • तीसरा, चाल को निष्पादक resolveऔर rejectकार्यों को बाद में एक्सेस करने में सक्षम होना है , इसलिए मैंने बस बंद के भीतर से उन्हें एक साधारण वस्तु में संग्रहीत किया है।

मुझे लगता है कि समाधान सरल है, और मैं इसके साथ कोई बड़ी समस्या नहीं देख सकता।

function wait(delay) {
  var promise;
  var timeOut;
  var executor={};
  promise=new Promise(function(resolve,reject) {
    console.log(`Started`);
    executor={resolve,reject};  //  Store the resolve and reject methods
    timeOut=setTimeout(function(){
      console.log(`Timed Out`);
      resolve();
    },delay);
  });
  //  Implement your own resolve methods,
  //  then access the stored methods
      promise.reject=function() {
        console.log(`Cancelled`);
        clearTimeout(timeOut);
        executor.reject();
      };
      promise.resolve=function() {
        console.log(`Finished`);
        clearTimeout(timeOut);
        executor.resolve();
      };
  return promise;
}

var promise;
document.querySelector('button#start').onclick=()=>{
  promise=wait(5000);
  promise
  .then(()=>console.log('I have finished'))
  .catch(()=>console.log('or not'));
};
document.querySelector('button#cancel').onclick=()=>{ promise.reject(); }
document.querySelector('button#finish').onclick=()=>{ promise.resolve(); }
<button id="start">Start</button>
<button id="cancel">Cancel</button>
<button id="finish">Finish</button>

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