নোড জেএস প্রতিশ্রুতি। সমস্ত এবং forEach


120

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

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

  1. নেস্টিংয়ের n স্তরের জন্য প্যাটার্নটি পুনরাবৃত্তিযোগ্য হওয়া উচিত।
  2. বদ্ধ রুটিন কখন সমাধান করবেন তা নির্ধারণ করার জন্য আমার প্রতিশ্রুতিবদ্ধ all সমস্ত বা একই জাতীয় কৌশল ব্যবহার করা উচিত।
  3. প্রতিটি উপাদান অ্যাসিঙ্ক কল করার জন্য অগত্যা জড়িত না। সুতরাং কোনও নেস্টেড প্রতিশ্রুতিতে all সমস্তই আমি সূচকের উপর ভিত্তি করে আমার জেএসওন অ্যারে উপাদানগুলিকে কেবল অ্যাসাইনমেন্ট দিতে পারি না। তবুও, প্রতিশ্রুতির মতো কিছু ব্যবহার করা দরকার। সমস্ত নেস্টেড ন্যাশনাল সমাধানের আগে সমস্ত সম্পত্তি বরাদ্দ করা হয়েছে তা নিশ্চিত করার জন্য প্রত্যেকটি নেস্টেড ফরেক্সে।
  4. আমি ব্লুবার্ড প্রতিশ্রুতি ব্যবহার করছি কিন্তু এটি কোনও প্রয়োজন নয়

এখানে কিছু আংশিক কোড দেওয়া হয়েছে -

var jsonItems = [];

items.forEach(function(item){

  var jsonItem = {};
  jsonItem.name = item.name;
  item.getThings().then(function(things){
  // or Promise.all(allItemGetThingCalls, function(things){

    things.forEach(function(thing, index){

      jsonItems[index].thingName = thing.name;
      if(thing.type === 'file'){

        thing.getFile().then(function(file){ //or promise.all?

          jsonItems[index].filesize = file.getSize();

এটি কার্যকারী উত্সের লিঙ্কটি যা আমি উন্নত করতে চাই। github.com/pebanfield/change-view-service/blob/master/src/…
ব্যবহারকারী3205931

1
আমি নমুনায় দেখতে পাচ্ছি যে আপনি ব্লুবার্ড ব্যবহার করছেন, ব্লুবার্ড আসলে আপনার জীবনকে (একযোগে) এবং (ক্রমযুক্ত) এর সাথে আরও সহজ করে তোলে , নোটটি অবচয় করা হয় - আমার উত্তরের কোডটি প্রতিশ্রুতি ফিরিয়ে কীভাবে এড়াতে হবে তা দেখায় । প্রতিশ্রুতি ফিরতি মান সম্পর্কে হয়। Promise.mapPromise.eachPromise.defer
বেনিয়ামিন গ্রুইনবাউম

উত্তর:


368

কিছু সাধারণ নিয়ম সহ এটি বেশ সোজা:

  • আপনি যখনই কোনও প্রতিশ্রুতি তৈরি করেন তখন thenতা ফিরিয়ে দিন - আপনি যে প্রতিশ্রুতি ফিরে করবেন না তা বাইরের জন্য অপেক্ষা করা হবে না।
  • আপনি যখনই একাধিক প্রতিশ্রুতি তৈরি করেন, .allসেগুলি - সেভাবে এটি সমস্ত প্রতিশ্রুতির জন্য অপেক্ষা করে এবং সেগুলির কোনও ত্রুটি চুপ করে যায় না।
  • আপনি যখনই বাসা thenবাঁধেন, আপনি সাধারণত মাঝখানে ফিরে আসতে পারেন - thenচেইনগুলি সাধারণত প্রায় 1 স্তরের গভীর।
  • আপনি যখনই আইও সঞ্চালন করবেন তখন এটি একটি প্রতিশ্রুতি সহ হওয়া উচিত - হয় এটি কোনও প্রতিশ্রুতিতে হওয়া উচিত অথবা এটি একটি প্রতিশ্রুতি তার সমাপ্তির ইঙ্গিত দেওয়ার জন্য ব্যবহার করা উচিত।

এবং কিছু টিপস:

  • ম্যাপিং ভাল সঙ্গে সম্পন্ন করা হয় .mapসঙ্গে তুলনায়for/push - একটি ফাংশন তুমি ম্যাপিং মূল্যবোধ, যদি mapদেয় আপনি সংক্ষেপে কর্ম একের পর এক এবং ফলাফল সমষ্টি প্রয়োগের ধারণা প্রকাশ করে।
  • কনক্যুরঞ্জি নিখরচায় ক্রমযুক্ত Promise.allক্রিয়াকলাপের চেয়ে আরও ভাল - একসাথে জিনিসগুলি কার্যকর করা এবং একের পর এক জিনিস সম্পাদন করার চেয়ে তাদের জন্য অপেক্ষা করা ভাল - প্রতিটি পরের অপেক্ষা করে।

ঠিক আছে, সুতরাং শুরু করা যাক:

var items = [1, 2, 3, 4, 5];
var fn = function asyncMultiplyBy2(v){ // sample async action
    return new Promise(resolve => setTimeout(() => resolve(v * 2), 100));
};
// map over forEach since it returns

var actions = items.map(fn); // run the function over all items

// we now have a promises array and we want to wait for it

var results = Promise.all(actions); // pass array of promises

results.then(data => // or just .then(console.log)
    console.log(data) // [2, 4, 6, 8, 10]
);

// we can nest this of course, as I said, `then` chains:

var res2 = Promise.all([1, 2, 3, 4, 5].map(fn)).then(
    data => Promise.all(data.map(fn))
).then(function(data){
    // the next `then` is executed after the promise has returned from the previous
    // `then` fulfilled, in this case it's an aggregate promise because of 
    // the `.all` 
    return Promise.all(data.map(fn));
}).then(function(data){
    // just for good measure
    return Promise.all(data.map(fn));
});

// now to get the results:

res2.then(function(data){
    console.log(data); // [16, 32, 48, 64, 80]
});

5
আহ, আপনার দৃষ্টিকোণ থেকে কিছু বিধি :-)
বার্গি

1
@ বার্গি কারও উচিত এই নিয়মের একটি তালিকা এবং প্রতিশ্রুতিগুলির একটি সংক্ষিপ্ত পটভূমি তৈরি করা উচিত। আমরা সম্ভবত এটি ব্লুবার্ডজ ডট কম এ হোস্ট করতে পারি।
বেনিয়ামিন গ্রুইনবাউম

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

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

2
@ ইউজার 3205931 প্রতিশ্রুতিগুলি সহজ নয়, বরং এটি সহজ - তারা অন্যান্য স্টাফের মতো পরিচিত নয় তবে একবার আপনি সেগুলি ছুঁড়ে ফেললে সেগুলি ব্যবহার করা আরও ভাল।
শক্তভাবে আটকাবেন

42

হ্রাস ব্যবহার করে এখানে একটি সাধারণ উদাহরণ। এটি ক্রমিকভাবে চলে, সন্নিবেশ ক্রম বজায় রাখে এবং ব্লুবার্ডের প্রয়োজন হয় না।

/**
 * 
 * @param items An array of items.
 * @param fn A function that accepts an item from the array and returns a promise.
 * @returns {Promise}
 */
function forEachPromise(items, fn) {
    return items.reduce(function (promise, item) {
        return promise.then(function () {
            return fn(item);
        });
    }, Promise.resolve());
}

এবং এটি এর মতো ব্যবহার করুন:

var items = ['a', 'b', 'c'];

function logItem(item) {
    return new Promise((resolve, reject) => {
        process.nextTick(() => {
            console.log(item);
            resolve();
        })
    });
}

forEachPromise(items, logItem).then(() => {
    console.log('done');
});

লুপে anচ্ছিক প্রসঙ্গটি প্রেরণে আমরা এটি দরকারী বলে মনে করেছি। প্রসঙ্গটি iteচ্ছিক এবং সমস্ত পুনরাবৃত্তি দ্বারা ভাগ করা হয়।

function forEachPromise(items, fn, context) {
    return items.reduce(function (promise, item) {
        return promise.then(function () {
            return fn(item, context);
        });
    }, Promise.resolve());
}

আপনার প্রতিশ্রুতি ফাংশনটি দেখতে এইরকম হবে:

function logItem(item, context) {
    return new Promise((resolve, reject) => {
        process.nextTick(() => {
            console.log(item);
            context.itemCount++;
            resolve();
        })
    });
}

এর জন্য ধন্যবাদ - আপনার সমাধানটি আমার পক্ষে কাজ করেছে যেখানে অন্যরা (বিভিন্ন এনএমপি লিবিস সহ) পায় নি। আপনি কি এনপিএম এ প্রকাশিত হয়েছে?
SamF

ধন্যবাদ. ফাংশন ধরে নেয় সমস্ত প্রতিশ্রুতি সমাধান হয়েছে। আমরা প্রত্যাখ্যাত প্রতিশ্রুতিগুলি কীভাবে পরিচালনা করব? এছাড়াও, আমরা কীভাবে একটি মূল্য দিয়ে সফল প্রতিশ্রুতিগুলি পরিচালনা করব?
ওয়ালহি

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

1

আমারও একই অবস্থা ছিল। আমি দুটি প্রতিশ্রুতি ব্যবহার করে সমাধান করেছি ll সমস্ত ()।

আমি মনে করি সত্যিই ভাল সমাধান ছিল, তাই আমি এটি এনপিএম এ প্রকাশ করেছি: https://www.npmjs.com/package/promise-foreach

আমি মনে করি আপনার কোডটি এরকম কিছু হবে

var promiseForeach = require('promise-foreach')
var jsonItems = [];
promiseForeach.each(jsonItems,
    [function (jsonItems){
        return new Promise(function(resolve, reject){
            if(jsonItems.type === 'file'){
                jsonItems.getFile().then(function(file){ //or promise.all?
                    resolve(file.getSize())
                })
            }
        })
    }],
    function (result, current) {
        return {
            type: current.type,
            size: jsonItems.result[0]
        }
    },
    function (err, newList) {
        if (err) {
            console.error(err)
            return;
        }
        console.log('new jsonItems : ', newList)
    })

0

কেবল উপস্থাপিত সমাধানটিতে যুক্ত করতে, আমার ক্ষেত্রে আমি পণ্যের তালিকার জন্য ফায়ারবেস থেকে একাধিক ডেটা আনতে চেয়েছিলাম। আমি এটি কীভাবে করেছি তা এখানে:

useEffect(() => {
  const fn = p => firebase.firestore().doc(`products/${p.id}`).get();
  const actions = data.occasion.products.map(fn);
  const results = Promise.all(actions);
  results.then(data => {
    const newProducts = [];
    data.forEach(p => {
      newProducts.push({ id: p.id, ...p.data() });
    });
    setProducts(newProducts);
  });
}, [data]);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.