আমি কীভাবে বিদ্যমান কলব্যাক এপিআইকে প্রতিশ্রুতিতে রূপান্তর করব?


721

আমি প্রতিশ্রুতি নিয়ে কাজ করতে চাই তবে আমার মতো ফর্ম্যাটটিতে একটি কলব্যাক এপিআই রয়েছে:

1. ডোম লোড বা অন্য এক সময় ইভেন্ট:

window.onload; // set to callback
...
window.onload = function() {

};

2. সাধারণ কলব্যাক:

function request(onChangeHandler) {
    ...
}
request(function() {
    // change happened
    ...
});

৩. নোড স্টাইলের কলব্যাক ("নোডব্যাক"):

function getStuff(dat, callback) {
    ...
}
getStuff("dataParam", function(err, data) {
    ...
})

4. নোড স্টাইল কলব্যাক্স সহ একটি সম্পূর্ণ গ্রন্থাগার:

API;
API.one(function(err, data) {
    API.two(function(err, data2) {
        API.three(function(err, data3) {
            ...
        });
    });
});

আমি প্রতিশ্রুতি হিসাবে এপিআইয়ের সাথে কীভাবে কাজ করব, কীভাবে আমি এটি "প্রতিশ্রুতি" দেব?


আমি আমার নিজের উত্তর পোস্ট করেছি তবে নির্দিষ্ট গ্রন্থাগারের জন্য কীভাবে এটি করা যায় সে সম্পর্কে উত্তরগুলি প্রসারিত হয় বা আরও পরিস্থিতিতে এবং সম্পাদনাগুলিও খুব স্বাগত।
বেনিয়ামিন গ্রুইনবাউম

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

একটি তৈরি করা কি new Promiseকোনও উল্লেখযোগ্য ওভারহেড যুক্ত করে? আমি আমার নোড অ্যাপ্লিকেশন থেকে সমস্ত সিঙ্ক্রোনাস কোডটি সরিয়ে ফেলতে একটি প্রতিশ্রুতিতে আমার সমস্ত সিঙ্ক্রোনাস Noje.js ফাংশনগুলি মোড়তে চাইছি, তবে এটি কি সেরা অনুশীলন? অন্য কথায়, একটি ফাংশন যা স্থির যুক্তি গ্রহণ করে (যেমন একটি স্ট্রিং) এবং গণনার ফলাফল দেয়, আমি কি প্রতিশ্রুতিতে এটি মোড়ানো উচিত? ... আমি কোথাও পড়েছি যে আপনার নোডেজে কোনও সিঙ্ক্রোনাস কোড না থাকা উচিত।
রনি রয়স্টন

1
@ রনরোস্টন নং, প্রতিশ্রুতি সহ সুসংগত কলগুলি গুটিয়ে ফেলা ভাল ধারণা নয় - কেবলমাত্র অ্যাসিনক্রোনাস কলই আই / ও করতে পারে
বেনজমিন গ্রুয়েনবাউম

উত্তর:


743

প্রতিশ্রুতিগুলির রাষ্ট্র থাকে, এগুলি মুলতুবি হিসাবে শুরু হয় এবং এগুলি নিষ্পত্তি করতে পারে:

  • পরিপূর্ণ অর্থ যে গণনাটি সফলভাবে শেষ হয়েছে।
  • প্রত্যাখাত অর্থ যে গণনা ব্যর্থ হয়েছে।

প্রতিশ্রুতি ফেরানোর ফাংশনগুলি কখনই ছুঁড়ে ফেলা উচিত নয় , পরিবর্তে তাদের প্রত্যাখ্যানগুলি ফিরিয়ে দেওয়া উচিত। প্রতিশ্রুতি ফেরত ফাংশন থেকে ছুড়ে ফেলা আপনাকে a } catch { এবং a উভয়ই ব্যবহার করতে বাধ্য করবে .catch। প্রতিশ্রুত এপিআই ব্যবহার করা লোকেরা প্রতিশ্রুতি নিক্ষেপ করার আশা করে না। আপনি যদি নিশ্চিত না হন যে async এপিআই কীভাবে জেএসে কাজ করে - দয়া করে এই উত্তরটি দেখুন প্রথমে ।

1. ডোম লোড বা অন্য এক সময় ইভেন্ট:

সুতরাং, প্রতিশ্রুতি তৈরির অর্থ সাধারণত তারা কখন সেটেল হয় তা নির্দিষ্ট করে দেওয়া হয় - এর অর্থ যখন তারা ডেটা উপলব্ধ থাকে তা নির্দেশ করতে পূর্ণ বা প্রত্যাখ্যানিত পর্যায়ে চলে যায় (এবং এর সাথে অ্যাক্সেস করা যায়) .then )।

Promiseদেশীয় ES6 প্রতিশ্রুতির মতো নির্মাতাকে সমর্থন করে এমন আধুনিক প্রতিশ্রুতি বাস্তবায়ন সহ :

function load() {
    return new Promise(function(resolve, reject) {
        window.onload = resolve;
    });
}

তারপরে আপনি ফলাফলটির প্রতিশ্রুতিটি এর মতো ব্যবহার করবেন:

load().then(function() {
    // Do things after onload
});

মুলতুবি সমর্থনকারী লাইব্রেরিগুলির সাথে (আসুন এখানে উদাহরণের জন্য $ q ব্যবহার করুন, তবে আমরা পরে jQueryও ব্যবহার করব):

function load() {
    var d = $q.defer();
    window.onload = function() { d.resolve(); };
    return d.promise;
}

বা এপিআই এর মতো জিকুয়ের সাথে একবারে ঘটে যাওয়া ইভেন্টের প্রতি ঝুঁকুন:

function done() {
    var d = $.Deferred();
    $("#myObject").once("click",function() {
        d.resolve();
    });
    return d.promise();
}

2. সাধারণ কলব্যাক:

এই এপিআইগুলি ভাল কারণ সাধারণ… কলব্যাকগুলি জেএসে সাধারণ। থাকার সাধারণ ক্ষেত্রে যাক চেহারা onSuccessএবং onFail:

function getUserData(userId, onLoad, onFail) { 

Promiseদেশীয় ES6 প্রতিশ্রুতির মতো নির্মাতাকে সমর্থন করে এমন আধুনিক প্রতিশ্রুতি বাস্তবায়ন সহ :

function getUserDataAsync(userId) {
    return new Promise(function(resolve, reject) {
        getUserData(userId, resolve, reject);
    });
}

মুলতুবি সমর্থনকারী লাইব্রেরিগুলির সাথে (আসুন এখানে উদাহরণের জন্য jQuery ব্যবহার করুন, তবে আমরা উপরে $ q ব্যবহার করেছি):

function getUserDataAsync(userId) {
    var d = $.Deferred();
    getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
    return d.promise();
}

jQuery এছাড়াও একটি $.Deferred(fn)ফর্ম প্রস্তাব করে , যা আমাদের এমন একটি এক্সপ্রেশন লিখতে অনুমতি দেয় যা ফর্মটি খুব কাছাকাছি অনুকরণ new Promise(fn)করে:

function getUserDataAsync(userId) {
    return $.Deferred(function(dfrd) {
        getUserData(userId, dfrd.resolve, dfrd.reject);
    }).promise();
}

দ্রষ্টব্য: এখানে আমরা jQuery স্থগিত resolveএবং rejectপদ্ধতিগুলি "বিচ্ছিন্ন"; এই সত্যটি কাজে লাগিয়েছি ; অর্থাত। তারা উদাহরণ হতে বাধ্য jQuery.Deferred () । সমস্ত libs এই বৈশিষ্ট্যটি সরবরাহ করে না।

৩. নোড স্টাইলের কলব্যাক ("নোডব্যাক"):

নোড স্টাইলের কলব্যাকস (নোডব্যাকস) এর একটি নির্দিষ্ট ফর্ম্যাট রয়েছে যেখানে কলব্যাকগুলি সর্বদা সর্বশেষ যুক্তি হিসাবে থাকে এবং এর প্রথম পরামিতিটি একটি ত্রুটি। আসুন প্রথমে ম্যানুয়ালি একটির প্রতিশ্রুতি দেওয়া যাক:

getStuff("dataParam", function(err, data) { 

প্রতি:

function getStuffAsync(param) {
    return new Promise(function(resolve, reject) {
        getStuff(param, function(err, data) {
            if (err !== null) reject(err);
            else resolve(data);
        });
    });
}

মুলতুবি দিয়ে আপনি নিম্নলিখিতটি করতে পারেন (আসুন Q উদাহরণস্বরূপ ব্যবহার করুন, যদিও Q এখন নতুন সিনট্যাক্সকে সমর্থন করে যা আপনার পছন্দ করা উচিত ):

function getStuffAsync(param) {
    var d = Q.defer();
    getStuff(param, function(err, data) {
        if (err !== null) d.reject(err);
        else d.resolve(data);
    });
    return d.promise;   
}

সাধারণভাবে, আপনাকে জিনিসগুলিকে ম্যানুয়ালি খুব বেশি প্রচার করা উচিত নয়, নোড 8+-এ নোড 8 এর সাথে স্থানীয় প্রতিশ্রুতিগুলি যেমন নোডের সাথে ডিজাইন করা হয়েছিল এমন বেশিরভাগ প্রতিশ্রুতি গ্রন্থাগারগুলির নোডব্যাকগুলি প্রতিশ্রুতি দেওয়ার জন্য একটি বিল্ট ইন পদ্ধতি রয়েছে। উদাহরণ স্বরূপ

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

4. নোড স্টাইল কলব্যাক্স সহ একটি সম্পূর্ণ গ্রন্থাগার:

এখানে কোনও সুবর্ণ নিয়ম নেই, আপনি একে একে প্রতিশ্রুতি দিন। যাইহোক, কিছু প্রতিশ্রুতি বাস্তবায়ন আপনাকে বাল্কে এটি করার অনুমতি দেয়, উদাহরণস্বরূপ ব্লুবার্ডে, নোডব্যাক এপিআইকে একটি প্রতিশ্রুতি এপিআইতে রূপান্তর করা তত সহজ:

Promise.promisifyAll(API);

অথবা সঙ্গে নেটিভ প্রতিশ্রুতি মধ্যে নোড :

const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
                         .reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

মন্তব্য:

  • অবশ্যই, আপনি যখন কোনও .thenহ্যান্ডলারের সাথে থাকবেন তখন আপনাকে জিনিসগুলি প্রচার করার দরকার নেই। কোনও .thenহ্যান্ডলারের কাছ থেকে কোনও প্রতিশ্রুতি ফিরিয়ে দেওয়া সেই প্রতিশ্রুতির মান সহ সমাধান বা প্রত্যাখ্যান করবে। নিক্ষেপ করা ক.thenহ্যান্ডলারের করাও ভাল অনুশীলন এবং প্রতিশ্রুতি প্রত্যাখ্যান করবে - এটি বিখ্যাত প্রতিশ্রুতি থ্রো নিরাপত্তা।
  • প্রকৃত onloadক্ষেত্রে, আপনার addEventListenerপরিবর্তে ব্যবহার করা উচিত onX

বেঞ্জামিন, আমি আপনার সম্পাদনা করার আমন্ত্রণটি স্বীকার করেছি এবং কেস ২-তে আরও jQuery উদাহরণ যুক্ত করেছি। এটি উপস্থিত হওয়ার আগে পিয়ার পর্যালোচনা করা দরকার। আশা করি এটা আপনার ভালো লেগেছে.
রোমের -1888

@ রোমের -1888 এটিকে প্রত্যাখ্যান করা হয়েছে যেহেতু আমি সময় মতো এটি দেখে নি এবং গ্রহণ করি নি। যার পক্ষে এটি মূল্যবান তার জন্য আমি যুক্ত মনে করি না যদিও এটি দরকারী তবে দরকারী।
বেনিয়ামিন গ্রুইনবাউম

2
বেঞ্জামিন, না হোক resolve()এবং reject()পুনঃব্যবহারযোগ্য হিসাবে লিখিত হোক না কেন , আমি উদ্যোগ নিয়েছি যে আমার প্রস্তাবিত সম্পাদনাটি প্রাসঙ্গিক কারণ এটি ফর্মের একটি jQuery উদাহরণ সরবরাহ করে $.Deferred(fn), যা অন্যথায় অভাবের। যদি কেবল একটি jQuery উদাহরণ অন্তর্ভুক্ত করা হয়, তবে আমি প্রস্তাব দিই যে এটি var d = $.Deferred();ইত্যাদির পরিবর্তে এটি এই ফর্মের হওয়া উচিত কারণ লোকেরা অবহেলিত $.Deferred(fn)ফর্মটি ব্যবহার করতে উত্সাহিত করা উচিত , প্লাস, এর মতো উত্তরে এটি jQuery কে আরও সমানভাবে রাখে লিব ব্যবহার প্রকাশক রচয়িতা প্যাটার্ন
রোমের -1888

হেই, আমি 100% ন্যায্য হতে চাই jQuery আপনাকে জানাতে দেয় না $.Deferred(fn), আপনি যদি পরবর্তী 15 মিনিটের মধ্যে বিদ্যমান উদাহরণের পরিবর্তে এটি সম্পাদনা করেন তবে আমি নিশ্চিত যে আমি সময়মতো এটি অনুমোদনের চেষ্টা করতে পারব :)
বেনজামিন গ্রুইনবাউম

7
এটি একটি দুর্দান্ত উত্তর। আপনি এটিকে উল্লেখ করে এটি আপডেট করতেও পারেন util.promisify, যে নোড.জেএস আরসি 8.0.0 থেকে শুরু করে এটির মূলটি যুক্ত করতে চলেছে। এটি কাজ করে এটি ব্লুবার্ডের থেকে খুব বেশি আলাদা নয় Promise.promisify, তবে আপনি যদি কেবল দেশীয় প্রতিশ্রুতি চান তবে অতিরিক্ত নির্ভরতা না লাগানোর সুবিধা রয়েছে। যারা এই বিষয়ে আরও পড়তে চান তার জন্য আমি ইউজার.প্রমিজিফাই সম্পর্কে একটি ব্লগ পোস্ট লিখেছি ।
ব্রুনো

55

আজকে আমি ব্যবহার করতে পারেন Promiseমধ্যে Node.jsএকটি প্লেইন জাভাস্ক্রিপ্ট পদ্ধতি হিসাবে।

Promise( KISS উপায় সহ) এর একটি সহজ এবং মৌলিক উদাহরণ :

সরল জাভাস্ক্রিপ্ট Async এপিআই কোড:

function divisionAPI (number, divider, successCallback, errorCallback) {

    if (divider == 0) {
        return errorCallback( new Error("Division by zero") )
    }

    successCallback( number / divider )

}

Promise জাভাস্ক্রিপ্ট Async এপিআই কোড:

function divisionAPI (number, divider) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            return rejected( new Error("Division by zero") )
        }

        fulfilled( number / divider )

     })

}

(আমি এই সুন্দর উত্সটি দেখার পরামর্শ দিই )

এছাড়াও Promiseএকসঙ্গে ব্যবহার করা যেতে পারে async\awaitযে ES7একটি জন্য প্রোগ্রাম প্রবাহ অপেক্ষা করতে fullfiledনিচের মত ফলাফল:

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


async function foo () {

    var name = await getName(); // awaits for a fulfilled result!

    console.log(name); // the console writes "John Doe" after 3000 milliseconds

}


foo() // calling the foo() method to run the code

.then()পদ্ধতি ব্যবহার করে একই কোড সহ আরেকটি ব্যবহার

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


// the console writes "John Doe" after 3000 milliseconds
getName().then(function(name){ console.log(name) })

Promiseনোড.জেএস-এর মতো কোনও প্ল্যাটফর্মের উপরও ব্যবহার করা যেতে পারে react-native

বোনাস : একটি হাইব্রিড পদ্ধতি
(কলব্যাক পদ্ধতিতে ত্রুটি এবং ফলাফল হিসাবে দুটি পরামিতি রয়েছে বলে ধরে নেওয়া হয়)

function divisionAPI (number, divider, callback) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            let error = new Error("Division by zero")
            callback && callback( error )
            return rejected( error )
        }

        let result = number / divider
        callback && callback( null, result )
        fulfilled( result )

     })

}

উপরের পদ্ধতিটি পুরানো ফ্যাশন কলব্যাক এবং প্রতিশ্রুতি ব্যবহারের ফলাফলের প্রতিক্রিয়া জানাতে পারে।

আশাকরি এটা সাহায্য করবে.


3
এগুলি প্রতিশ্রুতিতে রূপান্তর করার উপায় দেখায় বলে মনে হয় না।
দিমিত্রি জায়তসেভ

33

কোনও ফাংশনকে নোড.জেএস-এ প্রতিশ্রুতি হিসাবে রূপান্তর করার আগে

var request = require('request'); //http wrapped module

function requestWrapper(url, callback) {
    request.get(url, function (err, response) {
      if (err) {
        callback(err);
      }else{
        callback(null, response);             
      }      
    })
}


requestWrapper(url, function (err, response) {
    console.log(err, response)
})

এটি রূপান্তর করার পরে

var request = require('request');

function requestWrapper(url) {
  return new Promise(function (resolve, reject) { //returning promise
    request.get(url, function (err, response) {
      if (err) {
        reject(err); //promise reject
      }else{
        resolve(response); //promise resolve
      }
    })
  })
}


requestWrapper('http://localhost:8080/promise_request/1').then(function(response){
    console.log(response) //resolve callback(success)
}).catch(function(error){
    console.log(error) //reject callback(failure)
})

আপনি একাধিক অনুরোধ পরিচালনা করতে হবে

var allRequests = [];
allRequests.push(requestWrapper('http://localhost:8080/promise_request/1')) 
allRequests.push(requestWrapper('http://localhost:8080/promise_request/2'))
allRequests.push(requestWrapper('http://localhost:8080/promise_request/5'))    

Promise.all(allRequests).then(function (results) {
  console.log(results);//result will be array which contains each promise response
}).catch(function (err) {
  console.log(err)
});

23

আমি মনে করি না window.onload@ বেঞ্জামিনের পরামর্শটি সর্বদা কার্যকর হবে, কারণ এটি বোঝা যায় না যে এটি লোডের পরে ডাকা হয়েছিল কিনা। আমাকে বহুবার কামড়েছে। এখানে একটি সংস্করণ যা সর্বদা কাজ করা উচিত:

function promiseDOMready() {
    return new Promise(function(resolve) {
        if (document.readyState === "complete") return resolve();
        document.addEventListener("DOMContentLoaded", resolve);
    });
}
promiseDOMready().then(initOnLoad);

1
"ইতিমধ্যে সম্পূর্ণ" শাখাটি ব্যবহার করা উচিত নয় setTimeout(resolve, 0)(বা setImmediate, যদি পাওয়া যায়) এটি অ্যাসিক্রোনাসলি বলা হয়?
Alnitak

5
অ্যালনিটাক resolveসিঙ্ক্রোনসি কল করা ঠিক আছে। প্রতিশ্রুতিthen হ্যান্ডলারগুলি সিঙ্ক্রোনালি বলা হয় কিনা তা বিবেচনা না করেই কাঠামোটিকে অবিচ্ছিন্নভাবে ডাকা হবে বলে গ্যারান্টিযুক্তresolve
জেফ বোম্যান 21 ই

15

নোড.জেএস ৮.০.০ এ একটি নতুন util.promisify()এপিআই অন্তর্ভুক্ত করেছে যা মানক নোড.জেএস কলব্যাক স্টাইল এপিআইগুলিকে কোনও ফাংশনে আবৃত করতে দেয় যা প্রতিশ্রুতি দেয়। util.promisify()নীচে ব্যবহারের একটি উদাহরণ ব্যবহার করা হয়েছে।

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

readFile('/some/file')
  .then((data) => { /** ... **/ })
  .catch((err) => { /** ... **/ });

প্রতিশ্রুতি জন্য উন্নত সমর্থন দেখুন


2
ইতিমধ্যে এটি বর্ণনা করার জন্য দুটি উত্তর রয়েছে, তৃতীয়টি কেন পোস্ট করবেন?
বেনিয়ামিন গ্রুইনবাউম

1
নোডের সেই সংস্করণটি এখন প্রকাশিত হওয়ার কারণে এবং আমি "অফিসিয়াল" বৈশিষ্ট্য বিবরণ এবং লিঙ্কটি প্রতিবেদন করেছি।
জিয়ান মার্কো ঘেরার্ডি

14

নোড.জেএস ৮.০.০ এর মুক্তির প্রার্থী হিসাবে, একটি নতুন ইউটিলিটি রয়েছে, util.promisify(আমি ব্যবহার সম্পর্কে লিখেছি ify ), যা কিছু কার্যনির্বাহী করার ক্ষমতা সজ্জিত করে।

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

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

তারপরে আপনার কাছে readFileএমন একটি পদ্ধতি রয়েছে যা একটি নেটিভকে ফেরত দেয় Promise

readFile('./notes.txt')
  .then(txt => console.log(txt))
  .catch(...);

1
আরে, আমি (ওপি) আসলে util.promisifyদু'বার প্রস্তাব দিয়েছিলাম (২০১৪ সালে ফিরে যখন এই প্রশ্নটি লেখা হয়েছিল, এবং কয়েক মাস আগে - যা আমি নোডের মূল সদস্য হিসাবে চাপিয়েছিলাম এবং নোডে আমাদের বর্তমান সংস্করণটি রয়েছে)। যেহেতু এটি এখনও সর্বজনীনভাবে উপলভ্য নয় - আমি এখনও এই উত্তরে এটি যোগ করি নি। যদিও আমরা ব্যবহারের প্রতিক্রিয়াটির গভীরভাবে প্রশংসা করব এবং মুক্তির জন্য আরও ভাল ডক্স পেতে কিছু সমস্যাগুলি কী কী তা জানতে
পেরে

1
এছাড়াও, আপনি util.promisifyআপনার ব্লগ পোস্টে প্রতিশ্রুতি দেওয়ার জন্য কাস্টম পতাকাটি নিয়ে আলোচনা করতে চাইতে পারেন :)
বেনজামিন গ্রুইনবাউম

util.promisify.custom@ বেনজামিন গ্রুয়েনবাউম আপনি কি এই সত্যটি বোঝাতে চাইছেন যে প্রতীকটি ব্যবহার করে ব্যবহারকারীর ফলাফলকে ওভাররাইড করা সম্ভব? সত্য কথা বলতে গেলে এটি একটি ইচ্ছাকৃত মিস ছিল, কারণ আমি এখনও একটি দরকারী ব্যবহারের কেসটি খুঁজে পাচ্ছি না। সম্ভবত আপনি আমাকে কিছু ইনপুট দিতে পারেন?
ব্রুনো

1
নিশ্চিত, fs.existsনোড কনভেনশন অনুসরণ করে না এমন এপিআই বা এপিআইগুলিকে বিবেচনা করুন - একটি ব্লুবার্ড Promise.promisify তাদের ভুল পেতে পারে তবে util.promisifyসেগুলি সঠিকভাবে পায়।
বেনিয়ামিন গ্রুইনবাউম

7

আপনি জাভাস্ক্রিপ্ট নেটিভ প্রতিশ্রুতি নোড জেএস ব্যবহার করতে পারেন।

আমার মেঘ 9 কোড লিঙ্ক: https://ide.c9.io/adx2803/native-promises-in-node

/**
* Created by dixit-lab on 20/6/16.
*/

var express = require('express');
var request = require('request');   //Simplified HTTP request client.


var app = express();

function promisify(url) {
    return new Promise(function (resolve, reject) {
        request.get(url, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                resolve(body);
            }
            else {
                reject(error);
            }
        })
    });
}

//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
    //get the post with post id 100
    promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
        var obj = JSON.parse(result);
        return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
    })
    .catch(function (e) {
        console.log(e);
    })
    .then(function (result) {
        res.end(result);
    })
})

var server = app.listen(8081, function () {
    var host = server.address().address
    var port = server.address().port

    console.log("Example app listening at http://%s:%s", host, port)
})

//run webservice on browser : http://localhost:8081/listAlbums

7

সরল পুরানো ভ্যানিলা জাভা স্ক্রিপ্ট সহ, একটি এপিআই কলব্যাক প্রতিশ্রুতি দেওয়ার জন্য এখানে একটি সমাধান।

function get(url, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url);
        xhr.addEventListener('readystatechange', function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    console.log('successful ... should call callback ... ');
                    callback(null, JSON.parse(xhr.responseText));
                } else {
                    console.log('error ... callback with error data ... ');
                    callback(xhr, null);
                }
            }
        });
        xhr.send();
    }

/**
     * @function promisify: convert api based callbacks to promises
     * @description takes in a factory function and promisifies it
     * @params {function} input function to promisify
     * @params {array} an array of inputs to the function to be promisified
     * @return {function} promisified function
     * */
    function promisify(fn) {
        return function () {
            var args = Array.prototype.slice.call(arguments);
            return new Promise(function(resolve, reject) {
                fn.apply(null, args.concat(function (err, result) {
                    if (err) reject(err);
                    else resolve(result);
                }));
            });
        }
    }

var get_promisified = promisify(get);
var promise = get_promisified('some_url');
promise.then(function (data) {
        // corresponds to the resolve function
        console.log('successful operation: ', data);
}, function (error) {
        console.log(error);
});

6

ক্রিস্কোওয়ালের Q লাইব্রেরিতে কলব্যাক-টু-ওয়াইড ফাংশন অন্তর্ভুক্ত রয়েছে। এর মতো একটি পদ্ধতি:

obj.prototype.dosomething(params, cb) {
  ...blah blah...
  cb(error, results);
}

Q.ninvoke এর সাথে রূপান্তর করা যায়

Q.ninvoke(obj,"dosomething",params).
then(function(results) {
});

1
ক্যানোনিকাল উত্তর ইতিমধ্যে উল্লেখ করা হয়েছে Q.denodeify। আমাদের কি গ্রন্থাগার সহায়কদের উপর জোর দেওয়ার প্রয়োজন?
বার্গি

3
আমি এখানে গুগল হিসাবে দরকারী হিসাবে কিউ লিডস প্রতিশ্রুতিবদ্ধ সম্পর্কে খুঁজে পেয়েছি
এড সাইকস

4

যখন আপনার কয়েকটি ফাংশন রয়েছে যা কলব্যাক গ্রহণ করে এবং আপনি তাদের পরিবর্তে কোনও প্রতিশ্রুতি ফিরিয়ে দিতে চান আপনি রূপান্তরটি করতে এই ফাংশনটি ব্যবহার করতে পারেন।

function callbackToPromise(func){

    return function(){

        // change this to use what ever promise lib you are using
        // In this case i'm using angular $q that I exposed on a util module

        var defered = util.$q.defer();

        var cb = (val) => {
            defered.resolve(val);
        }

        var args = Array.prototype.slice.call(arguments);
        args.push(cb);    
        func.apply(this, args);

        return defered.promise;
    }
}

4

নোড v7.6 + এর অধীনে যা প্রতিশ্রুতি এবং অ্যাসিঙ্কে তৈরি করেছে:

// promisify.js
let promisify = fn => (...args) =>
    new Promise((resolve, reject) =>
        fn(...args, (err, result) => {
            if (err) return reject(err);
            return resolve(result);
        })
    );

module.exports = promisify;

ব্যবহারবিধি:

let readdir = require('fs').readdir;
let promisify = require('./promisify');
let readdirP = promisify(readdir);

async function myAsyncFn(path) {
    let entries = await readdirP(path);
    return entries;
}

3

Node.js 8 আপনি পারেন promisify বস্তুর পদ্ধতি মাছি উপর এই npm মডিউল ব্যবহার করছে:

https://www.npmjs.com/package/doasync

এটি Use.promisify এবং প্রক্সি ব্যবহার করে যাতে আপনার অবজেক্টগুলি অপরিবর্তিত থাকে। উইকম্যাপস ব্যবহার করে স্মৃতিচারণও করা হয়)। এখানে কিছু উদাহরন:

বস্তু সহ:

const fs = require('fs');
const doAsync = require('doasync');

doAsync(fs).readFile('package.json', 'utf8')
  .then(result => {
    console.dir(JSON.parse(result), {colors: true});
  });

ফাংশন সহ:

doAsync(request)('http://www.google.com')
  .then(({body}) => {
    console.log(body);
    // ...
  });

এমনকি আপনি স্থানীয় ব্যবহার করতে পারেন callএবং applyকিছু প্রসঙ্গ বাঁধতেও পারেন:

doAsync(myFunc).apply(context, params)
  .then(result => { /*...*/ });

2

সেটটাইমআউটের সাথে উদাহরণ দেওয়ার জন্য আপনি ES6 এ স্থানীয় প্রতিশ্রুতি ব্যবহার করতে পারেন :

enqueue(data) {

    const queue = this;
    // returns the Promise
    return new Promise(function (resolve, reject) {
        setTimeout(()=> {
                queue.source.push(data);
                resolve(queue); //call native resolve when finish
            }
            , 10); // resolve() will be called in 10 ms
    });

}

এই উদাহরণে, প্রতিশ্রুতি ব্যর্থ হওয়ার কোনও কারণ নেই, তাই reject()বলা হয় না।


2

কলব্যাক শৈলী (Node.js প্রায় সব ফাংশন এই শৈলী হয়) ফাংশন সর্বদা ভালো:

//fs.readdir(path[, options], callback)
fs.readdir('mypath',(err,files)=>console.log(files))

এই শৈলীতে একই বৈশিষ্ট্য রয়েছে:

  1. কলব্যাক ফাংশন শেষ যুক্তি দ্বারা পাস করা হয়।

  2. কলব্যাক ফাংশন সর্বদা ত্রুটিযুক্ত বিষয়টিকে এটি প্রথম যুক্তি হিসাবে গ্রহণ করে।

সুতরাং, আপনি এই স্টাইলটি দিয়ে কোনও ফাংশনকে রূপান্তর করতে একটি ফাংশন লিখতে পারেন:

const R =require('ramda')

/**
 * A convenient function for handle error in callback function.
 * Accept two function res(resolve) and rej(reject) ,
 * return a wrap function that accept a list arguments,
 * the first argument as error, if error is null,
 * the res function will call,else the rej function.
 * @param {function} res the function which will call when no error throw
 * @param {function} rej the function which will call when  error occur
 * @return {function} return a function that accept a list arguments,
 * the first argument as error, if error is null, the res function
 * will call,else the rej function
 **/
const checkErr = (res, rej) => (err, ...data) => R.ifElse(
    R.propEq('err', null),
    R.compose(
        res,
        R.prop('data')
    ),
    R.compose(
        rej,
        R.prop('err')
    )
)({err, data})

/**
 * wrap the callback style function to Promise style function,
 * the callback style function must restrict by convention:
 * 1. the function must put the callback function where the last of arguments,
 * such as (arg1,arg2,arg3,arg...,callback)
 * 2. the callback function must call as callback(err,arg1,arg2,arg...)
 * @param {function} fun the callback style function to transform
 * @return {function} return the new function that will return a Promise,
 * while the origin function throw a error, the Promise will be Promise.reject(error),
 * while the origin function work fine, the Promise will be Promise.resolve(args: array),
 * the args is which callback function accept
 * */
 const toPromise = (fun) => (...args) => new Promise(
    (res, rej) => R.apply(
        fun,
        R.append(
            checkErr(res, rej),
            args
        )
    )
)

আরও সংক্ষিপ্ততার জন্য, উপরে উদাহরণস্বরূপ ramda.js ব্যবহৃত হয়েছে। রামদা.জেএস ফাংশনাল প্রোগ্রামিংয়ের জন্য একটি দুর্দান্ত গ্রন্থাগার। উপরের কোডে, আমরা এটি ব্যবহার করেছি প্রয়োগ করেছি (জাভাস্ক্রিপ্টের মতো function.prototype.apply) এবং সংযোজন (জাভাস্ক্রিপ্টের মতো function.prototype.push)। সুতরাং, আমরা কলব্যাক স্টাইল ফাংশনটি এখন স্টাইল ফাংশন প্রতিশ্রুতিতে রূপান্তর করতে পারি:

const {readdir} = require('fs')
const readdirP = toPromise(readdir)
readdir(Path)
    .then(
        (files) => console.log(files),
        (err) => console.log(err)
    )

অঙ্গীকার এবং checkErr ফাংশন দ্বারা নিজের পাগল গ্রন্থাগার, এটি দ্বারা একটি কার্মিক প্রোগ্রামিং গ্রন্থাগার কাঁটাচামচ এর ramda.js (আমার দ্বারা তৈরি করুন)।

আশা করি এই উত্তরটি আপনার পক্ষে কার্যকর হবে।


2

আপনি এরকম কিছু করতে পারেন

// @flow

const toPromise = (f: (any) => void) => {
  return new Promise<any>((resolve, reject) => {
    try {
      f((result) => {
        resolve(result)
      })
    } catch (e) {
      reject(e)
    }
  })
}

export default toPromise

তারপরে এটি ব্যবহার করুন

async loadData() {
  const friends = await toPromise(FriendsManager.loadFriends)

  console.log(friends)
}

2
আরে, আমি নিশ্চিত নই যে এটি বিদ্যমান উত্তরের সাথে কী যুক্ত করে (সম্ভবত স্পষ্ট করা উচিত?) এছাড়াও, প্রতিশ্রুতিবদ্ধ কনস্ট্রাক্টরের অভ্যন্তরে চেষ্টা / ধরার দরকার নেই (এটি আপনার জন্য স্বয়ংক্রিয়ভাবে এটি করে)। এটি কী ধরণের কাজ করে তাও অস্পষ্ট (এটি সাফল্যের একক যুক্তি দিয়ে কলব্যাক কল করে? ত্রুটিগুলি কীভাবে পরিচালনা করা হয়?)
বেনজামিন গ্রুয়েনবাউম


1

আমার কোনও ক্রিয়াকলাপের সংস্করণ callbackহ'ল Pফাংশন:

var P = function() {
  var self = this;
  var method = arguments[0];
  var params = Array.prototype.slice.call(arguments, 1);
  return new Promise((resolve, reject) => {
    if (method && typeof(method) == 'function') {
      params.push(function(err, state) {
        if (!err) return resolve(state)
        else return reject(err);
      });
      method.apply(self, params);
    } else return reject(new Error('not a function'));
  });
}
var callback = function(par, callback) {
  var rnd = Math.floor(Math.random() * 2) + 1;
  return rnd > 1 ? callback(null, par) : callback(new Error("trap"));
}

callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))

P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))

Pফাংশন প্রয়োজন যে কলব্যাক স্বাক্ষর থাকতে হবে callback(error,result)


1
নেটিভ প্রতিশ্রুতি দেওয়া বা উপরের উত্তরগুলি দিয়ে এর কী সুবিধা রয়েছে?
বেনিয়ামিন গ্রুইনবাউম

দেশীয় প্রতিশ্রুতি দেওয়ার অর্থ কী?
loretoparisi


আহ হ্যাঁ অবশ্যই :) মূল ধারণাটি দেখানোর জন্য কেবল এবং উদাহরণ। প্রকৃতপক্ষে আপনি দেখতে পাচ্ছেন যে এমনকি স্থানীয় কোনও ব্যক্তিরও প্রয়োজন হয় যে ফাংশনের স্বাক্ষরটি অবশ্যই কিছু সংজ্ঞায়িত (err, value) => ...করতে হবে বা আপনাকে একটি কাস্টম সংজ্ঞা দিতে হবে (কাস্টম প্রতিশ্রুতিবদ্ধ ফাংশনগুলি দেখুন)। আপনাকে ধন্যবাদ ভাল ক্যাচা
loretoparisi

1
@ অ্যালোরিটোরিসি এফওয়াইআই, var P = function (fn, ...args) { return new Promise((resolve, reject) => fn.call(this, ...args, (error, result) => error ? reject(error) : resolve(result))); };আপনার মত একই কাজ করবে এবং এটি অনেক সহজ।
প্যাট্রিক রবার্টস

1

নীচে কোনও ফাংশন (কলব্যাক এপিআই) কীভাবে কোনও প্রতিশ্রুতিতে রূপান্তর করা যায় তার বাস্তবায়ন নীচে দেওয়া হল।

function promisify(functionToExec) {
  return function() {
    var array = Object.values(arguments);
    return new Promise((resolve, reject) => {
      array.push(resolve)
      try {
         functionToExec.apply(null, array);
      } catch (error) {
         reject(error)
      }
    })
  }
}

// USE SCENARIO

function apiFunction (path, callback) { // Not a promise
  // Logic
}

var promisedFunction = promisify(apiFunction);

promisedFunction('path').then(()=>{
  // Receive the result here (callback)
})

// Or use it with await like this
let result = await promisedFunction('path');

-2

এটি 5 বছর দেরির মতো, তবে আমি এখানে আমার প্রম্পেসিফ সংস্করণটি পোস্ট করতে চেয়েছিলাম যা কলব্যাকস এপিআই থেকে ফাংশন নেয় এবং তাদের প্রতিশ্রুতিতে রূপান্তরিত করে

const promesify = fn => {
  return (...params) => ({
    then: cbThen => ({
      catch: cbCatch => {
        fn(...params, cbThen, cbCatch);
      }
    })
  });
};

খুব সাধারণ সংস্করণটি এখানে দেখুন: https://gist.github.com/jdtorregrosas/aeee96dd07558a5d18db1ff02f31e21a


1
এটি কোনও প্রতিশ্রুতি নয়, এটি চেইন করে না, কলব্যাকের মধ্যে ফেলে দেওয়া ত্রুটিগুলি মোকাবেলা করে না বা ততক্ষণে দ্বিতীয় প্যারামিটার গ্রহণ করে ...
বেনজামিন গ্রুইনবাউম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.