একটি ভ্যানিলা ECMAScript 6 প্রতিশ্রুতি চেইন বাতিল করুন


110

.thenএকটি জাভাস্ক্রিপ্ট Promiseদৃষ্টান্তের গুলি সাফ করার জন্য কি কোনও পদ্ধতি আছে ?

আমি QUNit এর উপরে একটি জাভাস্ক্রিপ্ট পরীক্ষার কাঠামো লিখেছি । ফ্রেমওয়ার্কটি একে একে প্রতিটি চালিয়ে একযোগে পরীক্ষা চালায় 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()অংশগুলি সাফ করতে ব্যবহার করতে পারি 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()বিবৃতিটি বলা হচ্ছে না। ধারনা?

আপডেট 3

শেষ জিনিস খুঁজে বের করা। fn.call()আমি একটি ত্রুটি নিক্ষেপ করছিলাম যা আমি ধরিনি, সুতরাং পরীক্ষার প্রতিশ্রুতি at.promise.catch()এটি সমাধান করতে পারার আগে প্রত্যাখ্যান করেছিল ।


ES6 প্রতিশ্রুতি দিয়ে বাতিল করা সম্ভব তবে এটি প্রতিশ্রুতির সম্পত্তি নয় (বরং এটি এটি ফাংশনটির সম্পত্তি) এটি আপনার আগ্রহী হলে আমি একটি ছোট উদাহরণ তৈরি করতে পারি।
বেনিয়ামিন গ্রুইনবাউম

@ বেনজামিন গ্রুয়েনবাউম আমি জানি এটি প্রায় এক বছর কেটে গেছে, তবে আপনার কাছে উদাহরণ লেখার সময় পেলে আমি এখনও আগ্রহী। :)
dx_over_dt

1
এটি এক বছর আগে হয়েছে তবে গতকাল আনুষ্ঠানিকভাবে দু'দিন আগে আলোচনা টোকেন এবং বাতিলকরণের প্রতিশ্রুতি নিয়ে প্রথম পর্যায়ে চলে যাওয়ার বিষয়টি নিয়ে আলোচনা হয়েছে
বেনজামিন গ্রুইনবাউম

3
প্রতিশ্রুতি বাতিল করার ES6 উত্তরটি পর্যবেক্ষণযোগ্য। আপনি এখানে এ সম্পর্কে আরও পড়তে পারেন: github.com/Reactive-Extensions/RxJS
ফ্রাঙ্ক গোোরতানি

প্রতিশ্রুতি বাতিল করার জন্য লাইব্রেরিটি ব্যবহার করার বিষয়ে আমার উত্তরটির সাথে লিঙ্ক করা Prex
নাসেরটিও

উত্তর:


75

.thenএকটি জাভাস্ক্রিপ্ট প্রতিশ্রুতি উদাহরণ এর গুলি সাফ করার জন্য একটি পদ্ধতি আছে ?

কমপক্ষে ECMAScript 6 এ নেই। প্রতিশ্রুতি (এবং তাদের thenহ্যান্ডলারগুলি) ডিফল্টরূপে অবরুদ্ধ করা যায় (দুর্ভাগ্যক্রমে) । সেখানে আলোচনার একটি বিট স্প্যানিশ ভাষায়-আলোচনা (যেমন এখানে ) কিভাবে সঠিক ভাবে এই কাজটি সম্পর্কে, কিন্তু যাই হোক না কেন পদ্ধতির এটা ES6 অবতরণের করা হবে না জয় হবে।

বর্তমান অবস্থানটি হ'ল সাবক্লাসিং আপনার নিজের প্রয়োগ প্রয়োগ করে বাতিলযোগ্য প্রতিশ্রুতি তৈরি করতে অনুমতি দেবে (এটি কতটা ভাল কাজ করবে তা নিশ্চিত নয়)

ভাষা কমিটী যতক্ষণ না সেরা উপায় বের করে ফেলেছে (আশা করা যায় ES7?) আপনি এখনও ইউজারল্যান্ড প্রতিশ্রুতি বাস্তবায়ন ব্যবহার করতে পারেন, যার মধ্যে বেশিরভাগ বৈশিষ্ট্য বাতিল রয়েছে।

বর্তমান আলোচনাটি https://github.com/domenic/cancelable-promise এবং https://github.com/bergus/promise-cancellation খসড়াগুলিতে।


2
"কিছুটা আলোচনা" - আমি এসডিস্কাস বা গিটহাবের 30 টি থ্রেডের সাথে লিঙ্ক করতে পারি :) (ব্লুবার্ড ৩.০ এ বাতিল করার সাথে আপনার নিজের সহায়তার কথা উল্লেখ না করা)
বেঞ্জামিন গ্রুইনবাউম

@ বেঞ্জামিন গ্রুয়েনবাউম: আপনার কাছে কি এই লিঙ্কগুলি কোথাও ভাগ করে নেওয়ার জন্য প্রস্তুত? আমি দীর্ঘদিন ধরে মতামত এবং প্রচেষ্টা সংক্ষিপ্ত করতে এবং এসডিস্কাসের জন্য একটি প্রস্তাব পোস্ট করতে চেয়েছিলাম, তাই আমি যদি আমি কিছুই ভুলে যাই তা যদি আবার পরীক্ষা করতে পারি তবে আমি খুশি হব।
বার্গি

আমি তাদের কাজে কাজে লাগিয়েছি - তাই আমি 3-4 দিনের মধ্যে তাদের এনে দেব। ভাল শুরু করার জন্য আপনি প্রতিশ্রুতি-অ্যাপ্লাসের অধীনে প্রতিশ্রুতি বাতিলকরণের চেকটি পরীক্ষা করতে পারেন।
বেনিয়ামিন গ্রুইনবাউম

1
@ LUH3417: "স্বাভাবিক" ফাংশন কেবলমাত্র এক্ষেত্রে বিরক্তিকর। আপনি কোনও প্রোগ্রাম শুরু করেন এবং এটি শেষ না হওয়া পর্যন্ত অপেক্ষা করুন - বা আপনি killএটি এবং কীভাবে সম্ভবত প্রতিকূল পরিস্থিতি আপনার পরিবেশটি ফেলে রেখেছেন তা উপেক্ষা করুন (যাতে আপনি সাধারণত এটিও ফেলে দেন, যেমন কোনও অর্ধ-সমাপ্ত আউটপুট)। অ-ব্লকিং বা অ্যাসিঙ্ক্রোনাস ফাংশন তবে ইন্টারেক্টিভ অ্যাপ্লিকেশনগুলিতে কাজ করার জন্য নির্মিত, যেখানে আপনি চলমান ক্রিয়াকলাপগুলি কার্যকর করার ক্ষেত্রে এই জাতীয় সূক্ষ্ম নিয়ন্ত্রণ রাখতে চান।
বার্গি

6
ডোমেনিক টিসি 39 প্রস্তাবটি সরিয়ে নিয়েছে ... ... সিসি @ বেনজামিন গ্রুয়েনবাউম
সার্জিও

50

যদিও ES6 এ এটি করার কোনও মানক উপায় নেই তবে এটি পরিচালনা করার জন্য ব্লুবার্ড নামে একটি গ্রন্থাগার রয়েছে ।

প্রতিক্রিয়া ডকুমেন্টেশনের অংশ হিসাবে বর্ণিত একটি প্রস্তাবিত উপায়ও রয়েছে। এটি আপনার 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/ismmented-antipattern.html


1
বাতিল এই সংজ্ঞা কেবল প্রতিশ্রুতি প্রত্যাখ্যান করা হয়। এটি "বাতিল" এর সংজ্ঞা উপর নির্ভর করে।
আলেকজান্ডার মিলস 9

1
এবং যদি আপনি প্রতিশ্রুতিগুলির একটি সেট বাতিল করতে চান তবে কী হবে?
ম্যাথিউ ব্রুচার

1
এই পদ্ধতির সাথে সমস্যাটি যদি আপনার কাছে এমন কোনও প্রতিশ্রুতি থাকে যা কখনই সমাধান বা প্রত্যাখ্যান করবে না এটি কখনই বাতিল হবে না।
ড্যানিশ এইচ

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()ফলে লগটি কল করার ফলস্বরূপ ঘটবে। actual `` const वास्तविकপ্রোমস = নতুন প্রতিশ্রুতি ((সমাধান, প্রত্যাখ্যান) => {সেটটাইমআউট (())> কনসোল.লগ ('প্রকৃত নামে পরিচিত'); সমাধান () 100, 10000)}); `` `
shmck

2
প্রশ্নটি ছিল কীভাবে কোনও প্রতিশ্রুতি (=> চেইনগুলি thenকার্যকর করা বন্ধ করুন ), কীভাবে বাতিল করবেন setTimeout(=> clearTimeout) বা সিঙ্ক্রোনাস কোড নয়, যেখানে প্রতিটি লাইনের পরে যদি আপনি একটি স্থাপন না করেন ( if (canceled) return) এটি অর্জন করা যায় না। (এটি করবেন না)
ফোিনিক্সহান

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

@ ডিএক্স_ওভার_ডিটি হ্যাঁ, সম্পাদনা হ'ল টাইপস, ব্যাকরণগত ত্রুটিগুলি সংশোধন করে পোস্টগুলি উন্নত করা এবং সিনট্যাক্স হাইলাইটিং যুক্ত করা (যদি কেউ কেবল কোডের একগুচ্ছ পোস্ট করে তবে ইন্ডেন্ট না দেয় বা উদাহরণ হিসাবে it `with দিয়ে ট্যাগ করে না)। অতিরিক্ত ব্যাখ্যা বা বিষয়গুলির জন্য যুক্তি / ন্যায্যতাগুলির মতো মূল বিষয়বস্তু যুক্ত করা সাধারণত উত্তর পোস্ট করা ব্যক্তির পরিচ্ছন্নতা। আপনি মন্তব্যগুলিতে এটি নির্দ্বিধায় মুক্ত হন এবং ওপিকে মন্তব্য সম্পর্কে অবহিত করা হবে এবং তারপরে তার প্রতিক্রিয়া জানানো যাবে বা তারা কেবল আপনার পরামর্শটি পোস্টে অন্তর্ভুক্ত করতে পারে।
টাইলারএইচ

@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>

দ্রষ্টব্য: পলিফিল যুক্ত করা দরকার, সমস্ত ব্রাউজারে সমর্থিত নয়।

সরাসরি উদাহরণ

মার্জিত-লেক -5 জেএনএইচ 3 সম্পাদনা করুন


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();} 
 })
}

একটি মোড়ক সমাধান (কারখানা)

আমি যে সমাধানটি পেয়েছি তা হ'ল একটি বাতিল_হোল্ডার অবজেক্টটি পাস করা। এটি একটি বাতিল ফাংশন হবে। যদি এটির একটি বাতিল কার্য থাকে তবে তা বাতিলযোগ্য।

এই বাতিল ফাংশন ত্রুটি ('বাতিল') সহ প্রতিশ্রুতি প্রত্যাখ্যান করে।

সমাধানের আগে, প্রত্যাখ্যান করুন, বা অন_স্যান্সেল বাতিল ফাংশনটি বিনা কারণে ডেকে আটকান।

আমি ইঞ্জেকশন দিয়ে বাতিল ক্রিয়াটি পাস করতে সুবিধাজনক পেয়েছি

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

যদি আপনার কোডটি কোনও শ্রেণিতে স্থাপন করা হয় তবে আপনি তার জন্য একটি ডেকরেটর ব্যবহার করতে পারেন। আপনি এই ধরনের প্রসাধক আছে utils-আলোকচিত্রী ( 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()শীঘ্রই প্রস্থান করার জন্য canceled এটি খুব কার্যকরী, বিশেষত ওয়েব ওয়ার্কার্সে যাদের onmessageহ্যান্ডলারের কাছ থেকে প্রতিশ্রুতিতে বিদ্যমান মাইক্রোটাস্ক রয়েছে que

// 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

@ মিশেল ইয়াগুদেবের উত্তর আমার পক্ষে কাজ করে।

তবে আসল উত্তরটি রিচার্ড হ্যান্ডলিং হ্যান্ডেল করার জন্য .catch () দিয়ে মোড়ানো প্রতিশ্রুতিটিকে শৃঙ্খলাবদ্ধ করে না, @ মিশেল ইয়াগুদায়েবের উত্তরের শীর্ষে এখানে আমার উন্নতি রয়েছে:

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>

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.