আমি কীভাবে কোনও HTTP আনার () অনুরোধ বাতিল করব?


200

জাভাস্ক্রিপ্ট থেকে অনুরোধ করার জন্য একটি নতুন এপিআই রয়েছে: আনুন ()। ফ্লাইটে এই অনুরোধগুলি বাতিল করার জন্য কি কোনও বিল্ট ইন মেকানিজম রয়েছে?


পাঠাতে পারেন davidwalsh.name/cancel-fetch এছাড়াও
phirke গণেশ

উত্তর:


280

টি এল / ডিআর:

fetchএখন signal20 সেপ্টেম্বর 2017 হিসাবে একটি প্যারামিটার সমর্থন করে তবে সমস্ত ব্রাউজার এই মুহূর্তে এটি সমর্থন করে না

2020 আপডেট: বেশিরভাগ প্রধান ব্রাউজারগুলি (এজ, ফায়ারফক্স, ক্রোম, সাফারি, অপেরা এবং আরও কয়েকটি) বৈশিষ্ট্যটিকে সমর্থন করে যা ডিওএমের জীবনযাত্রার মানের অংশ হয়ে দাঁড়িয়েছে । (২০২০ সালের ২০ মার্চ পর্যন্ত)

এটি খুব শীঘ্রই আমরা দেখতে পাচ্ছি এমন একটি পরিবর্তন, এবং সুতরাং আপনার কোনও AbortControllerএস ব্যবহার করে একটি অনুরোধ বাতিল করতে সক্ষম হওয়া উচিত AbortSignal

দীর্ঘ সংস্করণ

কিভাবে:

এটি যেভাবে কাজ করে তা হ'ল:

ধাপ 1 : আপনি একটি তৈরি AbortController(আপাতত আমি শুধু ব্যবহার করা এই )

const controller = new AbortController()

পদক্ষেপ 2 : আপনি AbortControllerএস সিগন্যালটি এর মতো পান:

const signal = controller.signal

পদক্ষেপ 3 : আপনি signalএভাবে আনতে পাস করেন :

fetch(urlToFetch, {
    method: 'get',
    signal: signal, // <------ This is our AbortSignal
})

পদক্ষেপ 4 : যখনই আপনার প্রয়োজন হবে ঠিক তখনই বাতিল করুন:

controller.abort();

এটি কীভাবে কাজ করবে তার উদাহরণ এখানে রয়েছে (ফায়ারফক্স 57+ এ কাজ করে):

<script>
    // Create an instance.
    const controller = new AbortController()
    const signal = controller.signal

    /*
    // Register a listenr.
    signal.addEventListener("abort", () => {
        console.log("aborted!")
    })
    */


    function beginFetching() {
        console.log('Now fetching');
        var urlToFetch = "https://httpbin.org/delay/3";

        fetch(urlToFetch, {
                method: 'get',
                signal: signal,
            })
            .then(function(response) {
                console.log(`Fetch complete. (Not aborted)`);
            }).catch(function(err) {
                console.error(` Err: ${err}`);
            });
    }


    function abortFetching() {
        console.log('Now aborting');
        // Abort.
        controller.abort()
    }

</script>



<h1>Example of fetch abort</h1>
<hr>
<button onclick="beginFetching();">
    Begin
</button>
<button onclick="abortFetching();">
    Abort
</button>

সূত্র:


2
এই উত্তরটি সঠিক এবং এটি উত্সাহিত করা উচিত। তবে আমি কোড স্নিপেটে কিছু সম্পাদনা করার স্বাধীনতা নিয়েছিলাম, কারণ এটি আসলে ফায়ারফক্স 57+ এ কাজ করে না - শিম মনে হয়েছিল এটি ব্যর্থ হতে চলেছে ( "এরর: টাইপ এরিয়ার: 'সিগন্যাল' রিকোয়েস্টনিটির সদস্য) ইন্টারফেস অ্যাওর্টসিগনাল প্রয়োগ করে না। " ) এবং স্লোলি.আরবার্টমুরায়.কম.উইকের জন্য শংসাপত্রের সাথে কিছু সমস্যা আছে বলে মনে হচ্ছে ( " এই সার্ভারটি প্রমাণ করতে পারেনি যে এটি ধীরগতিতে। .herokuapp.com। " ), তাই আমি এটা ঠিক ব্যবহারের পরিবর্তিত slowwly.robertomurray.co.uk (সাধারণ HTTP)।
sideshowbarker

3
তবে এখন এটি অন্য ব্রাউজারগুলিতে যেমন ক্রোমের কাজ করে না কারণ এটি AbortController is not defined। যাইহোক, এটি ধারণার প্রমাণ মাত্র, ফায়ারফক্স 57+ এর সাথে কমপক্ষে লোকেরা এটি কাজ করতে দেখতে পারে
SudoPlz

3
এটি খাঁটি স্ট্যাকওভারফ্লো স্বর্ণ, সংক্ষিপ্ত লেখার জন্য ধন্যবাদ! এবং পাশাপাশি বাগট্র্যাকার লিঙ্কগুলি!
কেজেলস্কি


2
ধন্যবাদ তবে আমার এখনও একটি প্রশ্ন আছে, আমরা কি পরবর্তী ম্যানুয়ালি নিজে হাতে আনার জন্য সিগন্যালটি আবার সত্যে পরিবর্তন করা উচিত ??
অক্ষয় কিশোর

20

https://developers.google.com/web/updates/2017/09/abortable-fetch

https://dom.spec.whatwg.org/#aborting-ongoing-activities

// setup AbortController
const controller = new AbortController();
// signal to pass to fetch
const signal = controller.signal;

// fetch as usual
fetch(url, { signal }).then(response => {
  ...
}).catch(e => {
  // catch the abort if you like
  if (e.name === 'AbortError') {
    ...
  }
});

// when you want to abort
controller.abort();

প্রান্ত 16 (2017-10-17), ফায়ারফক্স 57 (2017-11-14), ডেস্কটপ সাফারি 11.1 (2018-03-29), আইওএস সাফারি 11.4 (2018-03-29), ক্রোম 67 (2018-05) -29), এবং পরে।


পুরানো ব্রাউজারগুলিতে, আপনি গিথুব-এর হোয়াটএইচজি-ফেচ পলিফিল এবং অ্যাবোর্টকন্ট্রোলার পলিফিল ব্যবহার করতে পারেন । আপনি পুরানো ব্রাউজারগুলি সনাক্ত করতে পারেন এবং শর্তসাপেক্ষে পলিফিলগুলিও ব্যবহার করতে পারেন :

import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
import {fetch} from 'whatwg-fetch'

// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch

যদি গিথুবের আনতে পলিফিল ব্যবহার করা হয় তবে এটির সাথে এটি করা সম্ভব, কেবল তাদের রেডমে
Fábio Santos

@ FábioSantos আপনার মন্তব্য প্রশ্নে থাকা উচিত, না উত্তর হিসাবে এটি নিজের অধিকার? এটি আমার উত্তরের সাথে সুনির্দিষ্ট মনে হচ্ছে না।
জয়েন

গিথুব আনতে পলিফিল ব্যবহার করা লোকদের জন্য কেবল একটি নোট। আমি ভেবেছিলাম এটি আপনার উত্তরের সাথে প্রাসঙ্গিক কারণ আফাইক এটি সর্বাধিক জনপ্রিয় আনার পলিফিল উপলভ্য এবং এটি আপনি যে ফাংশনটি ব্যবহার করছেন তা আনছে poly পুরানো ব্রাউজারগুলির কারণে প্রচুর লোক এই পলিফিলটি ব্যবহার করবে। আমি উল্লেখ করা গুরুত্বপূর্ণ মনে করলাম কারণ লোকেরা কেবলমাত্র পলিফিলগুলি সমস্ত কিছু ঠিক করে নেয়, তবে এই বিশেষ ব্যক্তিটি অ্যাওর্টকন্ট্রোলারকে পলিফিল দেওয়ার চেষ্টা করে না। পুরানো ব্রাউজারগুলিতে এটি পলিফিল হতে চলেছে এবং এলোমেলো করে ভেবে তারা অ্যাবার্টকন্ট্রোলার ব্যবহার করার চেষ্টা করবেন, কোনও কোণার ক্ষেত্রে এবং কেবল পুরানো ব্রাউজারগুলিতেই এর ব্যতিক্রম রয়েছে।
ফ্যাবিও

5

ফেব্রুয়ারী 2018 পর্যন্ত, fetch()Chrome এ নীচের কোড দিয়ে বাতিল করা যেতে পারে ( ফায়ারফক্স সমর্থন সক্ষম করতে পঠনযোগ্য স্ট্রিম ব্যবহার করে পড়ুন )। catch()বাছাইয়ের জন্য কোনও ত্রুটি নিক্ষেপ করা হয় না এবং AbortControllerএটি সম্পূর্ণরূপে অবলম্বন না করা পর্যন্ত এটি একটি অস্থায়ী সমাধান ।

fetch('YOUR_CUSTOM_URL')
.then(response => {
  if (!response.body) {
    console.warn("ReadableStream is not yet supported in this browser.  See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream")
    return response;
  }

  // get reference to ReadableStream so we can cancel/abort this fetch request.
  const responseReader = response.body.getReader();
  startAbortSimulation(responseReader);

  // Return a new Response object that implements a custom reader.
  return new Response(new ReadableStream(new ReadableStreamConfig(responseReader)));
})
.then(response => response.blob())
.then(data => console.log('Download ended. Bytes downloaded:', data.size))
.catch(error => console.error('Error during fetch()', error))


// Here's an example of how to abort request once fetch() starts
function startAbortSimulation(responseReader) {
  // abort fetch() after 50ms
  setTimeout(function() {
    console.log('aborting fetch()...');
    responseReader.cancel()
    .then(function() {
      console.log('fetch() aborted');
    })
  },50)
}


// ReadableStream constructor requires custom implementation of start() method
function ReadableStreamConfig(reader) {
  return {
    start(controller) {
      read();
      function read() {
        reader.read().then(({done,value}) => {
          if (done) {
            controller.close();
            return;
          }
          controller.enqueue(value);
          read();
        })
      }
    }
  }
}

2
এটি ওপি যা চেয়েছিল তা নয়। তারা পাঠককে নয়, ফেচটি বাতিল করতে চায়। অনুরোধটি শেষ না হওয়া পর্যন্ত আনার প্রতিশ্রুতি সমাধান হবে না, যা সার্ভারের কাছে অনুরোধটি বাতিল করতে দেরি হয়ে গেছে।
রহলি

3

@ স্প্রো যেমনটি বলেছে তেমন কোনও সঠিক সমাধান নেই।

তবে, আপনার যদি ফ্লাইটে প্রতিক্রিয়া থাকে এবং আপনি পঠনযোগ্য স্ট্রিম ব্যবহার করছেন তবে আপনি অনুরোধটি বাতিল করতে স্ট্রিমটি বন্ধ করতে পারেন।

fetch('http://example.com').then((res) => {
  const reader = res.body.getReader();

  /*
   * Your code for reading streams goes here
   */

  // To abort/cancel HTTP request...
  reader.cancel();
});

0

পলিফিল:

if(!AbortController){
  class AbortController {
    constructor() {
      this.aborted = false;
      this.signal = this.signal.bind(this);
    }
    signal(abortFn, scope) {
      if (this.aborted) {
        abortFn.apply(scope, { name: 'AbortError' });
        this.aborted = false;
      } else {
        this.abortFn = abortFn.bind(scope);
      }
    }
    abort() {
      if (this.abortFn) {
        this.abortFn({ reason: 'canceled' });
        this.aborted = false;
      } else {
        this.aborted = true;
      }
    }
  }

  const originalFetch = window.fetch;

  const customFetch = (url, options) => {
    const { signal } = options || {};

    return new Promise((resolve, reject) => {
      if (signal) {
        signal(reject, this);
      }
      originalFetch(url, options)
        .then(resolve)
        .catch(reject);
    });
  };

  window.fetch = customFetch;
}

মনে রাখবেন যে কোডটি পরীক্ষা করা হয়নি! আপনি যদি এটি পরীক্ষা করে থাকেন এবং কিছু কাজ না করে তবে আমাকে জানান। এটি আপনাকে সতর্কবার্তা দিতে পারে যে আপনি জাভাস্ক্রিপ্ট অফিসিয়াল লাইব্রেরি থেকে 'ফেচ' ফাংশনটি ওভাররাইট করার চেষ্টা করছেন।

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