Chrome এক্সটেনশান বার্তা পাস হচ্ছে: প্রতিক্রিয়া পাঠানো হয়নি


151

আমি সামগ্রী স্ক্রিপ্ট এবং এক্সটেনশনের মধ্যে বার্তা দেওয়ার চেষ্টা করছি

বিষয়বস্তু-স্ক্রিপ্টে আমার যা আছে তা এখানে

chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
  console.log(response)
});

এবং ব্যাকগ্রাউন্ড স্ক্রিপ্ট আমি

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.type == "getUrls"){
      getUrls(request, sender, sendResponse)
    }
});

function getUrls(request, sender, sendResponse){
  var resp = sendResponse;
  $.ajax({
    url: "http://localhost:3000/urls",
    method: 'GET',
    success: function(d){
      resp({urls: d})
    }
  });

}

এখন যদি আমি getUrlsফাংশনে এজাক্স কল করার আগে প্রতিক্রিয়াটি পাঠি , প্রতিক্রিয়াটি সফলভাবে প্রেরণ করা হয় তবে আমি আজব্যাকের সাফল্যের পদ্ধতিতে যখন প্রতিক্রিয়াটি প্রেরণ করি তবে তা প্রেরণ করে না, যখন আমি ডিবাগিংয়ে যাই তখন আমি দেখতে পাচ্ছি পোর্টটি sendResponseফাংশনের জন্য কোডের অভ্যর্থনীয়।


সেন্ডরেসপন্স প্যারামিটারের একটি রেফারেন্স সঞ্চয় করা সমালোচনা। এটি ছাড়া, প্রতিক্রিয়া অবজেক্টটি সুযোগের বাইরে চলে যায় এবং কল করা যায় না। কোডটির জন্য ধন্যবাদ যা আমাকে আমার সমস্যার সমাধানের দিকে ইঙ্গিত করেছিল!
ট্রিক্কিডিকি

হতে পারে আরও একটি সমাধান হ'ল প্রতিশ্রুতি সহ অ্যাসিঙ্ক ফাংশনটির ভিতরে সমস্ত কিছু গুটিয়ে ফেলা এবং অ্যাসিঙ্ক পদ্ধতির জন্য অপেক্ষা করা কল?
এনরিক

উত্তর:


348

এর জন্য ডকুমেন্টেশন থেকেchrome.runtime.onMessage.addListener :

ইভেন্ট শ্রোতার কাছ থেকে সত্য প্রত্যাবর্তন না করা অবধি যদি এই ইভেন্টটি শ্রোতা ফিরে আসে তখন এই ফাংশনটি অকার্যকর হয়ে যায় আপনি যদি অ্যাসিক্রোনিকভাবে কোনও প্রতিক্রিয়া প্রেরণ করতে চান তা বোঝাতে (এটি বার্তা চ্যানেলটিকে অন্য প্রান্তে খোলা রাখবে যতক্ষণ না সেন্ডারস্পোন না বলা হয়)।

সুতরাং আপনি return true;কলটি পরে যুক্ত করতে হবে getUrlsতা বোঝাতে যে আপনি প্রতিক্রিয়া ফাংশনটিকে অবিচ্ছিন্নভাবে কল করবেন।


এটি সঠিক, আমি আমার উত্তরে এটি স্বয়ংক্রিয় করার একটি উপায় যুক্ত করেছি
জিগ ম্যান্ডেল

62
এই জন্য +1। এই সমস্যাটি ডিবাগ করার চেষ্টা করার 2 দিনের অপচয় করার পরে এটি আমাকে বাঁচিয়েছে। আমি বিশ্বাস করতে পারি না যে এই বার্তাটি পাসিং গাইডে এখানে মোটেও উল্লেখ করা হয়নি: বিকাশকারী
ক্রোম

6
আমি সম্ভবত আগে এই সমস্যা ছিল; বুঝতে পেরে ফিরে এসেছি আমি ইতিমধ্যে এটি upvated ছিল। এটি পৃষ্ঠায় কোথাও বড় <blink>এবং <marquee>ট্যাগগুলিতে গা .় হওয়া দরকার।
কিউস - মনিকা

2
@ ফানফর্মস এফওয়াইআই, এই আচরণটি এখন মেসেজিং ডকুমেন্টেশনে নথিভুক্ত করা হয়েছে (পার্থক্যটি এখানে: কোড review.chromium.org/1874133002/patch/80001/90002 )।
রব ডব্লু

10
আমি শপথ করছি এটি আমি ব্যবহার করেছি সবচেয়ে অপ্রয়োজনীয় এপিআই।
মাইক্রেলসন্ডন

8

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

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
    handleMethod1(sendResponse);
}

কীভাবে জানতে পারি handleMethod1কলটি অ্যাসিঙ্ক হবে কি না? যে কেউ সংশোধন handleMethod1করে তা কীভাবে জানতে পারে যে এটি কোনও এসিংক পরিচয় করিয়ে কলকারীকে ভেঙে ফেলবে?

আমার সমাধানটি হ'ল:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {

    var responseStatus = { bCalled: false };

    function sendResponse(obj) {  //dummy wrapper to deal with exceptions and detect async
        try {
            sendResponseParam(obj);
        } catch (e) {
            //error handling
        }
        responseStatus.bCalled= true;
    }

    if (request.method == "method1") {
        handleMethod1(sendResponse);
    }
    else if (request.method == "method2") {
        handleMethod2(sendResponse);
    }
    ...

    if (!responseStatus.bCalled) { //if its set, the call wasn't async, else it is.
        return true;
    }

});

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


একটি বিষয় হ'ল কখনও কখনও আপনি প্রতিক্রিয়া ফাংশনটি কল করতে চাইবেন না এবং সেই ক্ষেত্রে আপনার মিথ্যা প্রত্যাবর্তন করা উচিত । আপনি যদি তা না করেন তবে আপনি বার্তার সাথে সম্পর্কিত সংস্থানগুলি ক্রোমকে আটকাতে বাধা দিচ্ছেন।
rsanchez

হ্যাঁ, কেন আমি কলব্যাক কল করতে ভোলার কথা বলিনি। এই বিশেষ ক্ষেত্রে আপনার মেন্যুনটি কনভেনশন করে পরিচালনা করা যেতে পারে যে হ্যান্ডলার (হ্যান্ডেলমাথোড 1 ইত্যাদি) "কোনও প্রতিক্রিয়া নয়" কেসটি নির্দেশ করতে মিথ্যা ফিরিয়ে দেয় (যদিও আইডি বরং সর্বদা একটি প্রতিক্রিয়া তোলে এমনকি একটি খালিও)। এইভাবে রক্ষণাবেক্ষণের সমস্যাটি কেবল সেই বিশেষ "নো রিটার্ন" ক্ষেত্রে স্থানীয় করা হয়।
জিগ ম্যান্ডেল

8
চাকাটি পুনরায় উদ্ভাবন করবেন না। অবজ্ঞাপিত chrome.extension.onRequest/ chrome.exension.sendRequestপদ্ধতিগুলি আপনার বর্ণনা অনুসারে ঠিক তেমন আচরণ করে। এই পদ্ধতিগুলি অবহেলা করা হয়েছে কারণ এটি দেখা গেছে যে অনেক এক্সটেনশন বিকাশকারী বার্তা পোর্ট বন্ধ করেনি। বর্তমান এপিআই (প্রয়োজনীয় return true) একটি আরও ভাল নকশা, কারণ নিরবভাবে ফাঁস হওয়ার চেয়ে কঠোর ব্যর্থ হওয়া ভাল।
রব ডব্লু

@ রবডাব্লু তবে সমস্যা কি তবে? আমার উত্তর দেবকে সত্য ফিরে যেতে ভুলতে বাধা দেয়।
জিগ ম্যান্ডেল

@ জিগম্যান্ডেল আপনি যদি কোনও প্রতিক্রিয়া পাঠাতে চান তবে কেবল ব্যবহার করুন return true;। কলটি সিঙ্ক করা থাকলে এটি পোর্টটিকে পরিষ্কার হতে বাধা দেয় না, যদিও অ্যাসিঙ্ক কলগুলি এখনও সঠিকভাবে প্রক্রিয়াজাত করা হচ্ছে। এই উত্তরের কোডটি আপাত কোনও লাভের জন্য অপ্রয়োজনীয় জটিলতার পরিচয় দেয়।
রব ডব্লিউ

2

কলব্যাক ছাড়াই ফায়ারফক্সের মাধ্যমে ক্রোম এবং এফএফ উভয় ক্ষেত্রেই এই কাজটি করতে আপনি আমার লাইব্রেরি https://github.com/lawlietmester/webextension ব্যবহার করতে পারেন ।

আপনার কোডটি দেখতে পাবেন:

Browser.runtime.onMessage.addListener( request => new Promise( resolve => {
    if( !request || typeof request !== 'object' || request.type !== "getUrls" ) return;

    $.ajax({
        'url': "http://localhost:3000/urls",
        'method': 'GET'
    }).then( urls => { resolve({ urls }); });
}) );
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.