একের পর এক প্রতিশ্রুতি সমাধান করুন (অর্থাত ক্রমানুসারে)?


269

নিম্নলিখিত কোডটি বিবেচনা করুন যা ক্রমিক / অনুক্রমিক পদ্ধতিতে ফাইলগুলির একটি অ্যারে পড়ে। readFilesপ্রতিশ্রুতি প্রদান করে, যা কেবল একবার সমাধান করা হয় যখন সমস্ত ফাইল ক্রমানুসারে পড়া হয়।

var readFile = function(file) {
  ... // Returns a promise.
};

var readFiles = function(files) {
  return new Promise((resolve, reject) => 

    var readSequential = function(index) {
      if (index >= files.length) {
        resolve();
      } else {
        readFile(files[index]).then(function() {
          readSequential(index + 1);
        }).catch(reject);
      }
    };

   readSequential(0); // Start!

  });
};

উপরের কোডটি কাজ করে, তবে জিনিসগুলি ধারাবাহিকভাবে ঘটে যাওয়ার জন্য আমার পুনরাবৃত্তি করতে পছন্দ করি না। এমন সহজ উপায় আছে যে এই কোডটি আবার লেখা যায় যাতে আমাকে আমার অদ্ভুত ব্যবহার করতে না হয়readSequential ক্রিয়াকলাপটি হয়?

মূলত আমি ব্যবহার করার চেষ্টা Promise.all, কিন্তু যে সব সৃষ্ট readFileএকই সময়ে ঘটতে, যা কল না আমি কি চাই:

var readFiles = function(files) {
  return Promise.all(files.map(function(file) {
    return readFile(file);
  }));
};

2
পূর্ববর্তী অ্যাসিনক্রোনাস অপারেশনটি শেষ করতে যে কোনও কিছু অপেক্ষা করতে হবে কলব্যাকের মধ্যে দিয়ে। প্রতিশ্রুতি ব্যবহার করে তা পরিবর্তন হয় না। সুতরাং আপনার পুনরাবৃত্তি প্রয়োজন।
বর্মার

1
এফওয়াইআই, স্ট্যাক ফ্রেম বিল্ড-আপ না হওয়ায় এটি প্রযুক্তিগতভাবে পুনরাবৃত্তি নয়। পূর্ববর্তীটি কল করার readFileSequential()আগেই ইতিমধ্যে ফিরে এসেছে (কারণ এটি অ্যাসিঙ্ক, এটি মূল ফাংশন কল ইতিমধ্যে ফিরে আসার অনেক পরে পূর্ণ হয়)।
jਫਰ00

1
@ jender00 স্ট্যাক ফ্রেমের জমা পুনরাবৃত্তির জন্য প্রয়োজনীয় নয় - কেবল স্ব-রেফারেন্স। যদিও এটি কেবল প্রযুক্তিগত।
বেনিয়ামিন গ্রুইনবাউম

3
@ বেনজামিন গ্রুয়েনবাউম - আমার বক্তব্যটি হ'ল পরের পুনরাবৃত্তিটি বন্ধ করতে ফাংশনটি কল করার সাথে একেবারেই কোনও ভুল নেই। এটির শূন্যতম দিক রয়েছে এবং প্রকৃতপক্ষে এটি অসিঙ্ক ক্রিয়াকলাপগুলিকে সিকোয়েন্স করার একটি কার্যকর উপায়। সুতরাং, পুনরাবৃত্তির মতো দেখতে এমন কিছু এড়ানোর কোনও কারণ নেই। অদক্ষ কিছু সমস্যার পুনরাবৃত্ত সমাধান রয়েছে - এটি এর মধ্যে একটি নয়।
jفر00

1
আরে, জাভাস্ক্রিপ্ট রুমে আলোচনার জন্য এবং অনুরোধের ভিত্তিতে আমি এই উত্তরটি সম্পাদনা করেছি যাতে আমরা অন্যকে এটি প্রচলিত হিসাবে চিহ্নিত করতে পারি। আপনি যদি মতানৈক্য করেন তবে দয়া করে আমাকে জানান এবং আমি এটিকে পুনরুদ্ধার করব এবং আলাদা একটি খুলব।
বেনজামিন গ্রুয়েনবাউম

উত্তর:


337

আপডেট 2017 : পরিবেশটি যদি সমর্থন করে তবে আমি একটি অ্যাসিঙ্ক ফাংশন ব্যবহার করব:

async function readFiles(files) {
  for(const file of files) {
    await readFile(file);
  }
};

যদি আপনি চান, অ্যাসিঙ্ক জেনারেটর (আপনার পরিবেশ যদি এটি সমর্থন করে) ব্যবহার করে আপনার প্রয়োজন না হওয়া পর্যন্ত আপনি ফাইলগুলি পড়া পিছিয়ে দিতে পারেন:

async function* readFiles(files) {
  for(const file of files) {
    yield await readFile(file);
  }
};

আপডেট: দ্বিতীয় চিন্তায় - আমি পরিবর্তে লুপের জন্য ব্যবহার করতে পারি:

var readFiles = function(files) {
  var p = Promise.resolve(); // Q() in q

  files.forEach(file =>
      p = p.then(() => readFile(file)); 
  );
  return p;
};

বা আরও কমপ্যাক্টভাবে, হ্রাস সহ:

var readFiles = function(files) {
  return files.reduce((p, file) => {
     return p.then(() => readFile(file));
  }, Promise.resolve()); // initial
};

অন্যান্য প্রতিশ্রুতি গ্রন্থাগারে (যেমন কখন এবং ব্লুবার্ড) এর জন্য আপনার কাছে ইউটিলিটি পদ্ধতি রয়েছে।

উদাহরণস্বরূপ, ব্লুবার্ডটি হ'ল:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));

var readAll = Promise.resolve(files).map(fs.readFileAsync,{concurrency: 1 });
// if the order matters, you can use Promise.each instead and omit concurrency param

readAll.then(function(allFileContents){
    // do stuff to read files.
});

যদিও আজকের মতো অ্যাসিঙ্কটি অপেক্ষা না করার সত্যিই কোনও কারণ নেই।


2
@ EmreTapcı, নাহ। একটি তীর ফাংশনের "=>" ইতিমধ্যে ফিরে আসা বোঝায়।
সর্বোচ্চ

আপনি যদি টাইপস্ক্রিপ্ট ব্যবহার করেন তবে আমি মনে করি যে "ইন" লুপ সমাধানটি সবচেয়ে ভাল। পুনরাবৃত্তি প্রতিশ্রুতি যেমন হ্রাস। প্রথম কল রিটার্ন টাইপ হ'ল প্রতিশ্রুতি <void>, তারপরে দ্বিতীয় প্রতিশ্রুতি <প্রতিশ্রুতি <void>> এবং আরও অনেক কিছু - আমি যে ভাবি
সেগুলি

@ আর্টারটিগিজো টাইপসক্রিপ্টটিতে (কমপক্ষে নতুন সংস্করণে) পুনরাবৃত্ত হওয়া টাইপ রয়েছে এবং এগুলি সঠিকভাবে এখানে সমাধান করা উচিত । প্রতিশ্রুতি <প্রতিশ্রুতি <টি>> বলে কিছু নেই যেহেতু "পুনরাবৃত্তির সাথে একীকরণ" প্রতিশ্রুতি রয়েছে। Promise.resolve(Promise.resolve(15))অনুরূপ Promise.resolve(15)
বেনিয়ামিন গ্রুইনবাউম


72

এখানে আমি সিরিজের কাজগুলি চালানো পছন্দ করি।

function runSerial() {
    var that = this;
    // task1 is a function that returns a promise (and immediately starts executing)
    // task2 is a function that returns a promise (and immediately starts executing)
    return Promise.resolve()
        .then(function() {
            return that.task1();
        })
        .then(function() {
            return that.task2();
        })
        .then(function() {
            console.log(" ---- done ----");
        });
}

আরও কাজ সঙ্গে কেস সম্পর্কে কি? 10 এর মত?

function runSerial(tasks) {
  var result = Promise.resolve();
  tasks.forEach(task => {
    result = result.then(() => task());
  });
  return result;
}

8
এবং যেসব ক্ষেত্রে আপনি কাজের সঠিক সংখ্যা জানেন না সেগুলি সম্পর্কে কী বলা যায়?
14:51

1
এবং যখন আপনি কাজের সংখ্যাটি জানেন তবে কী কেবল রানটাইম এ?
জোয়েটউইল

10
"আপনি কিছুতেই প্রতিশ্রুতির বিন্যাস পরিচালনা করতে চান না। প্রতিশ্রুতি অনুসারে প্রতিশ্রুতি তৈরি হওয়ার সাথে সাথে এটি কার্যকর করা শুরু করে। সুতরাং আপনি যা চান তা প্রতিশ্রুতি কারখানার একটি অ্যারে" দেখুন উন্নত ভুল # 3 এখানে: pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
16'11

5
আপনি যদি লাইনের শব্দ কমিয়ে result = result.then(task);
আনতে চান তবে

1
@ ড্যানিয়েলবাকমাস্টার হ্যাঁ, তবে সাবধান হন, যেহেতু যদি টাস্ক () কোনও মান দেয় তবে এটি পরবর্তী অনুরোধে পৌঁছে দেওয়া হবে। যদি আপনার টাস্কে alচ্ছিক যুক্তি থাকে তবে এটি পার্শ্ব প্রতিক্রিয়া তৈরি করতে পারে। বর্তমান কোড ফলাফলগুলি গ্রাস করে এবং স্পষ্টভাবে কোনও তর্ক ছাড়াই পরবর্তী কাজটি শুরু করে।
JHH

63

এই প্রশ্নটি পুরানো, তবে আমরা ES6 এবং কার্যকরী জাভাস্ক্রিপ্টের বিশ্বে বাস করি, সুতরাং আসুন আমরা কীভাবে উন্নতি করতে পারি তা দেখুন।

প্রতিশ্রুতি অবিলম্বে কার্যকর করা হয়েছে, আমরা কেবল প্রতিশ্রুতিগুলির একটি অ্যারে তৈরি করতে পারি না, তারা সমস্ত সমান্তরালে বন্ধ করে দেবে।

পরিবর্তে, আমাদের ফাংশনগুলির একটি অ্যারে তৈরি করা দরকার যা কোনও প্রতিশ্রুতি দেয়। প্রতিটি ফাংশন তারপরে ক্রমানুসারে কার্যকর করা হবে যা এরপরে অঙ্গীকার শুরু করে।

আমরা এটি কয়েকটি উপায়ে সমাধান করতে পারি তবে আমার প্রিয় উপায়টি ব্যবহার করা reduce

reduceপ্রতিশ্রুতিগুলির সাথে একত্রিত হয়ে এটি কিছুটা জটিল হয়ে ওঠে, তাই আমি এক লাইনারটিকে নীচে কিছু ছোট পাচ্য কামড়ায় ভেঙে ফেলেছি।

এই ফাংশনের সারমর্মটি হ'ল reduceপ্রাথমিক মান Promise.resolve([])বা শূন্য অ্যারেযুক্ত প্রতিশ্রুতি দিয়ে শুরু করা ব্যবহার করা ।

এই প্রতিশ্রুতি তারপর reduceপদ্ধতি হিসাবে পাস করা হবে promise। এটি প্রতিটি প্রতিশ্রুতি ধারাবাহিকভাবে শৃঙ্খলাবদ্ধ করার মূল চাবিকাঠি। সম্পাদন করার পরবর্তী প্রতিশ্রুতি হ'ল funcএবং যখন thenআগুন লাগে, ফলাফলগুলি সংক্ষিপ্ত হয় এবং সেই প্রতিশ্রুতি তারপরে ফিরে আসে, reduceপরবর্তী প্রতিশ্রুতি ফাংশন সহ চক্রটি কার্যকর করে ।

সমস্ত প্রতিশ্রুতি কার্যকর হয়ে গেলে, প্রত্যাশিত প্রতিশ্রুতিতে প্রতিশ্রুতির সমস্ত ফলাফলের একটি অ্যারে থাকবে।

ES6 উদাহরণ (একটি লাইনার)

/*
 * serial executes Promises sequentially.
 * @param {funcs} An array of funcs that return promises.
 * @example
 * const urls = ['/url1', '/url2', '/url3']
 * serial(urls.map(url => () => $.ajax(url)))
 *     .then(console.log.bind(console))
 */
const serial = funcs =>
    funcs.reduce((promise, func) =>
        promise.then(result => func().then(Array.prototype.concat.bind(result))), Promise.resolve([]))

ES6 উদাহরণ (ভাঙ্গা)

// broken down to for easier understanding

const concat = list => Array.prototype.concat.bind(list)
const promiseConcat = f => x => f().then(concat(x))
const promiseReduce = (acc, x) => acc.then(promiseConcat(x))
/*
 * serial executes Promises sequentially.
 * @param {funcs} An array of funcs that return promises.
 * @example
 * const urls = ['/url1', '/url2', '/url3']
 * serial(urls.map(url => () => $.ajax(url)))
 *     .then(console.log.bind(console))
 */
const serial = funcs => funcs.reduce(promiseReduce, Promise.resolve([]))

ব্যবহার:

// first take your work
const urls = ['/url1', '/url2', '/url3', '/url4']

// next convert each item to a function that returns a promise
const funcs = urls.map(url => () => $.ajax(url))

// execute them serially
serial(funcs)
    .then(console.log.bind(console))

1
খুব ভাল, ধন্যবাদ, Array.prototype.concat.bind(result)আমি যে অংশটি অনুপস্থিত ছিল তা
হ'ল, ফলস্বরূপ ফলদানের কাজটি

যেহেতু আমরা সবাই আধুনিক জেএস সম্পর্কে আছি, আমি বিশ্বাস করি console.log.bind(console)আপনার শেষ উদাহরণের বিবৃতিটি এখন সাধারণত অপ্রয়োজনীয়। এই দিনগুলিতে আপনি কেবল পাস করতে পারেন console.log। যেমন। serial(funcs).then(console.log)। বর্তমান নোডেজ এবং ক্রোমে পরীক্ষিত।
মলম্বি

আমার মাথাটি চারপাশে মুড়িয়ে ফেলার জন্য এটি কিছুটা শক্ত ছিল তবে হ্রাসটি মূলত এই সঠিকটি করছে? Promise.resolve([]).then((x) => { const data = mockApi('/data/1'); return Promise.resolve(x.concat(data)) }).then((x) => { const data = mockApi('/data/2'); return Promise.resolve(x.concat(data)); });
ডানেকানডো

@ লাডানেকানডো, হ্যাঁ এটি সঠিক দেখাচ্ছে। আপনি প্রতিশ্রুতিও ছেড়ে দিতে পারেন the রিটার্নে সমাধান করুন, প্রত্যাশিত রেস.কে রিজেক্ট না করা পর্যন্ত প্রত্যাশিত কোনও মান স্বয়ংক্রিয়ভাবে সমাধান হয়ে যাবে।
joelnet

@ জোয়েলনেট, ড্যানেকানডোর মন্তব্যের প্রতিক্রিয়া হিসাবে, আমি মনে করি যে কি হ্রাস করা উচিত তা নিম্নলিখিত মত প্রকাশে আরও সঠিকভাবে প্রকাশ করা উচিত, আপনি কি একমত? Promise.resolve([]).then(x => someApiCall('url1').then(r => x.concat(r))).then(x => someApiCall('url2').then(r => x.concat(r)))এবং
এরপরে

37

এটি কেবল ES6 এ করতে:

function(files) {
  // Create a new empty promise (don't do that with real people ;)
  var sequence = Promise.resolve();

  // Loop over each file, and add on a promise to the
  // end of the 'sequence' promise.
  files.forEach(file => {

    // Chain one computation onto the sequence
    sequence = 
      sequence
        .then(() => performComputation(file))
        .then(result => doSomething(result)); 
        // Resolves for each file, one at a time.

  })

  // This will resolve after the entire chain is resolved
  return sequence;
}

1
দেখে মনে হচ্ছে এটি আন্ডারস্কোর ব্যবহার করছে। files.forEachফাইলগুলি যদি একটি অ্যারে হয় তবে আপনি সরল করতে পারবেন ।
গুস্তাভো রডরিগস

2
ভাল ... এটি ES5। ES6 উপায় হবে for (file of files) {...}
গুস্তাভো রডরিগস

1
আপনি বলেছেন যে Promise.resolve()বাস্তব জীবনে ইতিমধ্যে সমাধান হওয়া প্রতিশ্রুতি তৈরি করতে আপনার ব্যবহার করা উচিত নয় । কেন না? Promise.resolve()তুলনায় পরিষ্কার মনে হচ্ছে new Promise(success => success())
ক্যানাক 21

8
@ ক্যান্যাক দুঃখিত, এটি শব্দের উপর একটি নাটক ("ফাঁকা প্রতিশ্রুতি ..") সহ একটি রসিকতা ছিল। অবশ্যই Promise.resolve();আপনার কোড ব্যবহার করুন।
শ্রীধর গুপ্ত

1
দুর্দান্ত সমাধান, অনুসরণ করা সহজ। আমি শেষে একটি ফাংশনে খনি ঘিরা করা হয়নি, তাই সমাধান করতে পরিবর্তে নির্বাণ return sequence;আমি করাsequence.then(() => { do stuff });
জো কোয়েল;

25

স্ট্যান্ডার্ড নোড.জেএস প্রতিশ্রুতি জন্য সহজ ব্যবহার:

function sequence(tasks, fn) {
    return tasks.reduce((promise, task) => promise.then(() => fn(task)), Promise.resolve());
}

হালনাগাদ

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


6
আমি আরও বিস্তারিতভাবে এটি দেখতে দেখতে চাই।
টাইগুই 7

আমি নীচের ব্যাখ্যা সহ এই উত্তরটির একটি প্রকরণ সরবরাহ করেছি। ধন্যবাদ
Sarsaparilla

প্রাক-নোড 7 পরিবেশগুলিতে অ্যাসিঙ্ক / অপেক্ষার অ্যাক্সেস না পেয়ে আমি ঠিক এটি করি। সুন্দর এবং পরিষ্কার।
জেএইচ এইচ

11

আমাকে প্রচুর অনুক্রমিক কাজ চালাতে হয়েছিল এবং এই উত্তরগুলি এমন কোনও ফাংশন জালিয়াতি করতে ব্যবহার করেছে যা কোনও ক্রমিক ক্রিয়াকলাপটি পরিচালনা করার যত্ন নেবে ...

function one_by_one(objects_array, iterator, callback) {
    var start_promise = objects_array.reduce(function (prom, object) {
        return prom.then(function () {
            return iterator(object);
        });
    }, Promise.resolve()); // initial
    if(callback){
        start_promise.then(callback);
    }else{
        return start_promise;
    }
}

ফাংশনটিতে 2 টি আর্গুমেন্ট + 1 optionচ্ছিক লাগে। প্রথম যুক্তি হ'ল অ্যারে যা আমরা কাজ করব। দ্বিতীয় যুক্তিটি হ'ল টাস্কটি নিজেই, একটি ফাংশন যা প্রতিশ্রুতি দেয়, পরবর্তী কাজটি কেবল তখনই শুরু করা হবে যখন এই প্রতিশ্রুতিটি সমাধান হয়। তৃতীয় আর্গুমেন্টটি সমস্ত কাজ শেষ হয়ে গেলে চালানোর জন্য একটি কলব্যাক। যদি কোনও কলব্যাক পাস না হয়, তবে ফাংশনটি এটি তৈরি প্রতিশ্রুতি দেয় যাতে আমরা শেষটি পরিচালনা করতে পারি।

ব্যবহারের উদাহরণ এখানে:

var filenames = ['1.jpg','2.jpg','3.jpg'];
var resize_task = function(filename){
    //return promise of async resizing with filename
};
one_by_one(filenames,resize_task );

আশা করি এটি কারও কিছুটা সময় সাশ্রয় করেছে ...


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

আপনার মন্তব্যের জন্য ধন্যবাদ! আমি সেই নামটিও ব্যবহার করছি না, তবে আমি এটি এখানে আরও স্পষ্ট / সহজ করে তুলতে চাই।
সালকেটার

5

আমি খুঁজে পেতে সক্ষম হয়েছি যে সর্বোত্তম সমাধানটি ছিল bluebirdপ্রতিশ্রুতি সহ। আপনি কেবল Promise.resolve(files).each(fs.readFileAsync);যা করতে পারেন তার গ্যারান্টি দেয় যে প্রতিশ্রুতিগুলি ক্রমানুসারে সমাধান করা হয়।


1
আরও ভাল করে: Promise.each(filtes, fs.readFileAsync)। বিটিডব্লিউ, আপনার কি করতে হবে না .bind(fs)?
বার্গি

এখানে আর কেউ আরে এবং সিকোয়েন্সের মধ্যে পার্থক্য বুঝতে পারে বলে মনে হয় না, যেটি পরে সীমাহীন / গতিশীল আকারকে বোঝায়।
প্রাণবন্ত- t

নোট করুন যে জাভাস্ক্রিপ্টে অ্যারেগুলি সি স্টাইলের ভাষাগুলিতে স্থির আকারের অ্যারেগুলির সাথে কোনও সম্পর্ক রাখে না। এগুলি কেবল সাংখ্যিক কী পরিচালিত বল্ট্টযুক্ত, এবং কোনও নির্দিষ্ট আকার বা সীমা নেই ( বিশেষত ব্যবহার করার সময় নয় new Array(int)that যা সমস্ত lengthকী-মান জোড়াটি প্রিসেট করে , দৈর্ঘ্য-ভিত্তিক পুনরাবৃত্তির সময় কতগুলি সূচক ব্যবহৃত হয় তা প্রভাবিত করে zero এটি শূন্য রয়েছে প্রকৃত অ্যারের সূচি বা সূচি সীমার উপর প্রভাব)
মাইক 'পোম্যাক্স' কামারম্যানস

4

এটি উপরের অন্য উত্তরের একটি সামান্য প্রকরণ। স্থানীয় প্রতিশ্রুতি ব্যবহার:

function inSequence(tasks) {
    return tasks.reduce((p, task) => p.then(task), Promise.resolve())
}

ব্যাখ্যা

আপনার যদি এই কাজগুলি থাকে [t1, t2, t3]তবে উপরেরটি সমানPromise.resolve().then(t1).then(t2).then(t3) । এটা হ্রাস করার আচরণ।

ব্যবহারবিধি

প্রথমে আপনাকে কাজের তালিকা তৈরি করতে হবে! একটি কার্য একটি ফাংশন যা কোনও যুক্তি গ্রহণ করে না। আপনার যদি আপনার ফাংশনে আর্গুমেন্টগুলি পাস করার দরকার হয় তবে bindকোনও টাস্ক তৈরির জন্য বা অন্যান্য পদ্ধতি ব্যবহার করুন । উদাহরণ স্বরূপ:

var tasks = files.map(file => processFile.bind(null, file))
inSequence(tasks).then(...)

4

আমার পছন্দের সমাধান:

function processArray(arr, fn) {
    return arr.reduce(
        (p, v) => p.then((a) => fn(v).then(r => a.concat([r]))),
        Promise.resolve([])
    );
}

এটি এখানে প্রকাশিত অন্যদের থেকে মৌলিকভাবে পৃথক নয় তবে:

  • সিরিজের আইটেমগুলিতে ফাংশন প্রয়োগ করে
  • ফলাফলের অ্যারেতে সমাধান হয়
  • অ্যাসিঙ্ক / অপেক্ষা করতে হবে না (সমর্থনটি এখনও বেশ সীমাবদ্ধ, প্রায় 2017)
  • তীর ফাংশন ব্যবহার করে; সুন্দর এবং সংক্ষিপ্ত

ব্যবহারের উদাহরণ:

const numbers = [0, 4, 20, 100];
const multiplyBy3 = (x) => new Promise(res => res(x * 3));

// Prints [ 0, 12, 60, 300 ]
processArray(numbers, multiplyBy3).then(console.log);

যুক্তিসঙ্গত বর্তমান ক্রোম (v59) এবং নোডজেএস (v8.1.2) এ পরীক্ষিত।


3

ব্যবহার করুন Array.prototype.reduce, এবং মনে রাখবেন কোনও ফাংশনে আপনার প্রতিশ্রুতি মোড়ানো অন্যথায় তারা ইতিমধ্যে চলমান থাকবে!

// array of Promise providers

const providers = [
  function(){
     return Promise.resolve(1);
  },
  function(){
     return Promise.resolve(2);
  },
  function(){
     return Promise.resolve(3);
  }
]


const inSeries = function(providers){

  const seed = Promise.resolve(null); 

  return providers.reduce(function(a,b){
      return a.then(b);
  }, seed);
};

সুন্দর এবং সহজ ... আপনার সম্পাদনা ইত্যাদির জন্য একই বীজ পুনরায় ব্যবহার করতে সক্ষম হওয়া উচিত

হ্রাস ব্যবহার করার সময় খালি অ্যারে বা অ্যারে থেকে কেবল 1 টি উপাদান দিয়ে রক্ষা করা গুরুত্বপূর্ণ , সুতরাং এই কৌশলটি আপনার সেরা বাজি:

   const providers = [
      function(v){
         return Promise.resolve(v+1);
      },
      function(v){
         return Promise.resolve(v+2);
      },
      function(v){
         return Promise.resolve(v+3);
      }
    ]

    const inSeries = function(providers, initialVal){

        if(providers.length < 1){
            return Promise.resolve(null)
        }

        return providers.reduce((a,b) => a.then(b), providers.shift()(initialVal));
    };

এবং তারপরে এটিকে কল করুন:

inSeries(providers, 1).then(v => {
   console.log(v);  // 7
});

2

প্রতিশ্রুতি বস্তুতে আমি এই সহজ পদ্ধতিটি তৈরি করেছি:

প্রতিশ্রুতি বস্তুতে একটি প্রতিশ্রুতি.সামগ্রী পদ্ধতি তৈরি করুন এবং যুক্ত করুন

Promise.sequence = function (chain) {
    var results = [];
    var entries = chain;
    if (entries.entries) entries = entries.entries();
    return new Promise(function (yes, no) {
        var next = function () {
            var entry = entries.next();
            if(entry.done) yes(results);
            else {
                results.push(entry.value[1]().then(next, function() { no(results); } ));
            }
        };
        next();
    });
};

ব্যবহার:

var todo = [];

todo.push(firstPromise);
if (someCriterium) todo.push(optionalPromise);
todo.push(lastPromise);

// Invoking them
Promise.sequence(todo)
    .then(function(results) {}, function(results) {});

প্রতিশ্রুতি বস্তুতে এই সম্প্রসারণ সম্পর্কে সর্বোত্তম জিনিসটি হ'ল এটি প্রতিশ্রুতির স্টাইলের সাথে সামঞ্জস্যপূর্ণ। প্রতিশ্রুতি.আল ও প্রতিশ্রুতি.সিকোয়েন্সগুলি একইভাবে ডাকা হয়, তবে বিভিন্ন শব্দার্থক শব্দ রয়েছে।

সতর্ক করা

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


না, আপনি তুলনা করতে পারবেন না Promise.allএবং আপনার Promise.sequence। একটি প্রতিশ্রুতি পুনরাবৃত্তি গ্রহণ করে না, অন্যটি প্রতিশ্রুতি ফেরত ফাংশনগুলির একটি অ্যারে নেয়।
বার্গি


এটি একটি পুনরুদ্ধারকারী গ্রহণ করেছে তা জানেন না। যদিও এটি পুনরায় লেখার জন্য যথেষ্ট সহজ হওয়া উচিত। আপনি কি ব্যাখ্যা করতে পারেন যে প্রতিশ্রুতিবদ্ধ কনস্ট্রাক্টর অ্যান্টিপ্যাটার্টার এটি কেন? আমি এখানে আপনার পোস্ট পড়তে হয়নি: stackoverflow.com/a/25569299/1667011
frodeborli

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

হ্যাঁ, আপনি যদি এটি একটি লাইব্রেরির ফাংশন হিসাবে বিবেচনা করেন তবে এটি ঠিক আছে, তবে এখনও এই ক্ষেত্রে reduceবেনজামিনের উত্তরটির মত একটি উত্তর অনেক সহজ।
বার্গি

2

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

function executeSequentially(promiseFactories) {
    var result = Promise.resolve();
    promiseFactories.forEach(function (promiseFactory) {
        result = result.then(promiseFactory);
    });
    return result;
}

প্রতিশ্রুতি কারখানা একটি সাধারণ কাজ যা একটি প্রতিশ্রুতি দেয়:

function myPromiseFactory() {
    return somethingThatCreatesAPromise();
}

এটি কাজ করে কারণ একটি প্রতিশ্রুতি কারখানাটি যখন না বলা পর্যন্ত প্রতিশ্রুতি তৈরি করে না। এটি তৎকালীন ফাংশন হিসাবে একইভাবে কাজ করে - বাস্তবে, এটি একই জিনিস!

আপনি মোটেও প্রতিশ্রুতিগুলির বিন্যাস পরিচালনা করতে চান না। প্রতিশ্রুতি অনুযায়ী, প্রতিশ্রুতি তৈরি হওয়ার সাথে সাথে এটি কার্যকর করা শুরু করে। সুতরাং আপনি কী চান তা প্রতিশ্রুতি কারখানার একটি অ্যারে ...

যদি আপনি প্রতিশ্রুতি সম্পর্কে আরও জানতে চান তবে আপনার এই লিঙ্কটি পরীক্ষা করা উচিত: https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html


2

আমার উত্তর https://stackoverflow.com/a/31070150/7542429 এর উপর ভিত্তি করে ।

Promise.series = function series(arrayOfPromises) {
    var results = [];
    return arrayOfPromises.reduce(function(seriesPromise, promise) {
      return seriesPromise.then(function() {
        return promise
        .then(function(result) {
          results.push(result);
        });
      });
    }, Promise.resolve())
    .then(function() {
      return results;
    });
  };

এই সমাধানটি প্রতিশ্রুতি.এল () এর মতো অ্যারে হিসাবে ফলাফলগুলি প্রদান করে।

ব্যবহার:

Promise.series([array of promises])
.then(function(results) { 
  // do stuff with results here
});

2

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

// first take your work
const urls = ['/url1', '/url2', '/url3', '/url4']

// next convert each item to a function that returns a promise
const functions = urls.map((url) => {
  // For every url we return a new function
  return () => {
    return new Promise((resolve) => {
      // random wait in milliseconds
      const randomWait = parseInt((Math.random() * 1000),10)
      console.log('waiting to resolve in ms', randomWait)
      setTimeout(()=>resolve({randomWait, url}),randomWait)
    })
  }
})


const promiseReduce = (acc, next) => {
  // we wait for the accumulator to resolve it's promise
  return acc.then((accResult) => {
    // and then we return a new promise that will become
    // the new value for the accumulator
    return next().then((nextResult) => {
      // that eventually will resolve to a new array containing
      // the value of the two promises
      return accResult.concat(nextResult)
    })
  })
};
// the accumulator will always be a promise that resolves to an array
const accumulator = Promise.resolve([])

// we call reduce with the reduce function and the accumulator initial value
functions.reduce(promiseReduce, accumulator)
  .then((result) => {
    // let's display the final value here
    console.log('=== The final result ===')
    console.log(result)
  })

2

বার্গি যেমন লক্ষ্য করেছেন, আমি মনে করি সবচেয়ে ভাল এবং স্পষ্ট সমাধান নীচের কোড ব্লুবার্ড.ইচ ব্যবহার করুন:

const BlueBird = require('bluebird');
BlueBird.each(files, fs.readFileAsync);

2

প্রথমত, আপনার বুঝতে হবে যে সৃষ্টির সময় একটি প্রতিশ্রুতি কার্যকর করা হয়।
সুতরাং উদাহরণস্বরূপ যদি আপনার একটি কোড থাকে:

["a","b","c"].map(x => returnsPromise(x))

আপনার এটিকে পরিবর্তন করতে হবে:

["a","b","c"].map(x => () => returnsPromise(x))

তারপরে আমাদের ক্রমাগত প্রতিশ্রুতিগুলি শৃঙ্খলাবদ্ধ করা দরকার:

["a", "b", "c"].map(x => () => returnsPromise(x))
    .reduce(
        (before, after) => before.then(_ => after()),
        Promise.resolve()
    )

সম্পাদনকারী after(), নিশ্চিত করবে যে প্রতিশ্রুতি কেবল তখনই আসে যখন তা কার্যকর হয় (এবং কার্যকর করা হয়)।


1

প্রতিশ্রুতি অবজেক্টটি প্রসারিত করতে আমি নিম্নলিখিত কোডটি ব্যবহার করি। এটি প্রতিশ্রুতি প্রত্যাখ্যান পরিচালনা করে এবং ফলাফলগুলির একটি অ্যারে প্রদান করে

কোড

/*
    Runs tasks in sequence and resolves a promise upon finish

    tasks: an array of functions that return a promise upon call.
    parameters: an array of arrays corresponding to the parameters to be passed on each function call.
    context: Object to use as context to call each function. (The 'this' keyword that may be used inside the function definition)
*/
Promise.sequence = function(tasks, parameters = [], context = null) {
    return new Promise((resolve, reject)=>{

        var nextTask = tasks.splice(0,1)[0].apply(context, parameters[0]); //Dequeue and call the first task
        var output = new Array(tasks.length + 1);
        var errorFlag = false;

        tasks.forEach((task, index) => {
            nextTask = nextTask.then(r => {
                output[index] = r;
                return task.apply(context, parameters[index+1]);
            }, e=>{
                output[index] = e;
                errorFlag = true;
                return task.apply(context, parameters[index+1]);
            });
        });

        // Last task
        nextTask.then(r=>{
            output[output.length - 1] = r;
            if (errorFlag) reject(output); else resolve(output);
        })
        .catch(e=>{
            output[output.length - 1] = e;
            reject(output);
        });
    });
};

উদাহরণ

function functionThatReturnsAPromise(n) {
    return new Promise((resolve, reject)=>{
        //Emulating real life delays, like a web request
        setTimeout(()=>{
            resolve(n);
        }, 1000);
    });
}

var arrayOfArguments = [['a'],['b'],['c'],['d']];
var arrayOfFunctions = (new Array(4)).fill(functionThatReturnsAPromise);


Promise.sequence(arrayOfFunctions, arrayOfArguments)
.then(console.log)
.catch(console.error);

1

আপনি যদি চান তবে অনুক্রমিক প্রতিশ্রুতি করতে হ্রাস ব্যবহার করতে পারেন, উদাহরণস্বরূপ:

[2,3,4,5,6,7,8,9].reduce((promises, page) => {
    return promises.then((page) => {
        console.log(page);
        return Promise.resolve(page+1);
    });
  }, Promise.resolve(1));

এটি সর্বদা অনুক্রমিকভাবে কাজ করবে।


1

আধুনিক ES ব্যবহার:

const series = async (tasks) => {
  const results = [];

  for (const task of tasks) {
    const result = await task;

    results.push(result);
  }

  return results;
};

//...

const readFiles = await series(files.map(readFile));

1

Async / Await এর সাথে (যদি আপনার ES7 এর সমর্থন থাকে)

function downloadFile(fileUrl) { ... } // This function return a Promise

async function main()
{
  var filesList = [...];

  for (const file of filesList) {
    await downloadFile(file);
  }
}

(আপনাকে অবশ্যই forলুপটি ব্যবহার করতে হবে , এবং এটি নয় forEachকারণ অ্যাসিঙ্ক / অপেক্ষার জন্য প্রতিটি লুপের জন্য সমস্যা রয়েছে)

অ্যাসিঙ্ক / অপেক্ষা ছাড়া (প্রতিশ্রুতি ব্যবহার করে)

function downloadFile(fileUrl) { ... } // This function return a Promise

function downloadRecursion(filesList, index)
{
  index = index || 0;
  if (index < filesList.length)
  {
    downloadFile(filesList[index]).then(function()
    {
      index++;
      downloadRecursion(filesList, index); // self invocation - recursion!
    });
  }
  else
  {
    return Promise.resolve();
  }
}

function main()
{
  var filesList = [...];
  downloadRecursion(filesList);
}

2
প্রত্যেকের জন্য অপেক্ষা করা বাঞ্ছনীয় নয়।
মার্সেলো আগিমিভেল

@ MarceloAgimóvel - আমি সঙ্গে কাজ না করার সমাধান আপডেট করেছি forEach(অনুযায়ী এই )
গিল Epshtain

0

প্রশ্নের শিরোনামের ভিত্তিতে, "একের পর এক প্রতিশ্রুতি সমাধান করুন (অর্থাত ক্রমানুসারে)?", আমরা বুঝতে পারি যে ওপিতে প্রতি সিক্যুয়াল কলগুলির চেয়ে নিষ্পত্তির প্রতিশ্রুতিগুলির সিক্যুয়ালি হ্যান্ডেলিংয়ের প্রতি আরও আগ্রহী

এই উত্তর দেওয়া হয়:

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

যদি একযোগে কলগুলি প্রকৃতপক্ষে না চাওয়া হয় তবে বেঞ্জামিন গ্রুইনবাউমের উত্তরটি দেখুন যা ক্রমানুসারে ক্রমবর্ধমান কলগুলি (ইত্যাদি) কভার করে।

তবে, আপনি এমন নিদর্শনগুলিতে আগ্রহী (উন্নত পারফরম্যান্সের জন্য) যা প্রতিক্রিয়াগুলির ক্রমিক ক্রম পরিচালনা করে সমবর্তী কলগুলি মঞ্জুরি দেয় তবে দয়া করে পড়ুন।

আপনাকে ভাবতে হবে Promise.all(arr.map(fn)).then(fn)(যেমন আমি অনেকবার করেছি) বা একটি প্রতিশ্রুতিবাদীর অভিনব চিনি (বিশেষত ব্লুবার্ডের) ব্যবহার করতে হবে তা ভেবে লোভনীয় , তবে ( এই নিবন্ধটির কৃতিত্বের সাথে ) একটি arr.map(fn).reduce(fn)প্যাটার্ন কাজটি করবে, এর সুবিধাগুলি সহ:

  • যে কোনও প্রতিশ্রুতি lib- এর সাথে কাজ করে - এমনকি jQuery এর প্রাক-সম্মতিযুক্ত সংস্করণ - কেবল .then()ব্যবহৃত হয়।
  • ওভার-ত্রুটি ছেড়ে যাওয়া বা অন-ত্রুটি বন্ধ করতে নমনীয়তাটিকে সমর্থন করে, আপনি যে কোনও একটি লাইন মোডের মাধ্যমে চান।

এটি এখানে, জন্য লেখা Q

var readFiles = function(files) {
    return files.map(readFile) //Make calls in parallel.
    .reduce(function(sequence, filePromise) {
        return sequence.then(function() {
            return filePromise;
        }).then(function(file) {
            //Do stuff with file ... in the correct sequence!
        }, function(error) {
            console.log(error); //optional
            return sequence;//skip-over-error. To stop-on-error, `return error` (jQuery), or `throw  error` (Promises/A+).
        });
    }, Q()).then(function() {
        // all done.
    });
};

দ্রষ্টব্য: কেবলমাত্র একটি টুকরা, Q() Q- এর সাথে সুনির্দিষ্ট j A + libs সহ, ​​বিদেশী প্রতিশ্রুতি একীভূত হবে।

কী এখানে হ্রাস কারো নির্দেশ চলে না sequenceপ্রতিশ্রুতি, যা সিকোয়েন্স হ্যান্ডলিং এর readFileপ্রতিশ্রুতি না কিন্তু তাদের সৃষ্টি।

এবং একবার আপনি এটি শোষিত হয়ে গেলে, আপনি যখন বুঝতে পারবেন যে .map()মঞ্চটি আসলে প্রয়োজনীয় নয়! পুরো কাজটি, সমান্তরাল কলগুলি এবং সঠিক ক্রমে সিরিয়াল হ্যান্ডলিংয়ের সাথে reduce()একাকী অর্জিত হতে পারে , আরও আরও নমনীয়তার অতিরিক্ত সুবিধা:

  • সমান্তরাল অ্যাসিঙ্ক কলগুলি থেকে সিরিয়াল অ্যাসিঙ্ক কলগুলিতে রূপান্তর করুন কেবল একটি লাইন স্থানান্তরিত করে - বিকাশের সময় সম্ভবত কার্যকর।

এখানে এটি Qআবার জন্য ।

var readFiles = function(files) {
    return files.reduce(function(sequence, f) {
        var filePromise = readFile(f);//Make calls in parallel. To call sequentially, move this line down one.
        return sequence.then(function() {
            return filePromise;
        }).then(function(file) {
            //Do stuff with file ... in the correct sequence!
        }, function(error) {
            console.log(error); //optional
            return sequence;//Skip over any errors. To stop-on-error, `return error` (jQuery), or `throw  error` (Promises/A+).
        });
    }, Q()).then(function() {
        // all done.
    });
};

এটিই বেসিক প্যাটার্ন। যদি আপনি কলারের কাছে ডেটা (যেমন ফাইল বা তাদের কোনও রূপান্তর) সরবরাহ করতে চান তবে আপনার হালকা বৈকল্পিকের প্রয়োজন হবে।


আমি মনে করি না যে ওপিএসের উদ্দেশ্যগুলির বিপরীতে প্রশ্নের উত্তর দেওয়া ভাল ধারণা ...
বার্গি

1
এই sequence.then(() => filePromise)জিনিসটি একটি অ্যান্টিপ্যাটার্ন - এটি যত তাড়াতাড়ি সম্ভব ত্রুটিগুলি প্রচার করে না (এবং unhandledRejectionতাদের সমর্থন করে এমন লিবস তৈরি করে)। আপনি বরং ব্যবহার করা উচিত Q.all([sequence, filePromise])বা $.when(sequence, filePromise)। স্বীকার করা যায়, আপনি যখন ত্রুটিগুলি উপেক্ষা বা এড়িয়ে যাওয়ার লক্ষ্য রাখেন তখন এই আচরণটি আপনি যা চান তা হতে পারে তবে আপনার অন্তত অসুবিধা হিসাবে এটি উল্লেখ করা উচিত।
বার্গি

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

1
হ্যাঁ, তার কোডের তৃতীয় সংস্করণে (এটি "সমান্তরাল এবং ক্রম উভয়" উভয়ই) একই সমস্যা। "অ্যান্টিপ্যাটার্ন" -কে পরিশীলিত ত্রুটি পরিচালনা করা দরকার এবং হ্যান্ডলারের সংশ্লেষিতভাবে সংযুক্ত করার ঝুঁকি রয়েছে, যা unhandledRejectionঘটনার কারণ করে। ব্লুবার্ডে আপনি sequence.return(filePromise)একই ব্যবহার করে এটি প্রত্যাখ্যান করতে পারেন তবে প্রত্যাখ্যানকে সূক্ষ্মভাবে পরিচালনা করে। আমি কোনও রেফারেন্স জানি না, আমি কেবল এটি নিয়ে এসেছি - "" (বিরোধী) প্যাটার্নটির কোনও নাম আছে বলে আমি মনে করি না।
বার্গি

1
@ বেরগি, আপনি পরিষ্কারভাবে দেখতে পাচ্ছেন যে আমি পারছি না :( আমি ভাবছি যে এই নতুন বিরোধী-প্যাটার্নটি কোথাও নথিভুক্ত করা দরকার?
রোমার-1888

0

আপনার দৃষ্টিভঙ্গিটি খারাপ নয়, তবে এর দুটি বিষয় রয়েছে: এটি ত্রুটিগুলি গ্রাস করে এবং এটি সুস্পষ্ট প্রতিশ্রুতি নির্মাণ এন্টিপ্যাটার্ন নিয়োগ করে।

আপনি এখনও একই সাধারণ কৌশলটি নিযুক্ত করার সময় এই দুটি সমস্যা সমাধান করতে এবং কোড ক্লিনার করতে পারেন:

var Q = require("q");

var readFile = function(file) {
  ... // Returns a promise.
};

var readFiles = function(files) {
  var readSequential = function(index) {
    if (index < files.length) {
      return readFile(files[index]).then(function() {
        return readSequential(index + 1);
      });
    }
  };

  // using Promise.resolve() here in case files.length is 0
  return Promise.resolve(readSequential(0)); // Start!
};

0

CRUD ক্রিয়াকলাপ সম্পাদন করার সময় যদি অন্য কারও কাছে প্রতিশ্রুতি সমাধানের দৃ of় ধারাবাহিক পদ্ধতির একটি গ্যারান্টিযুক্ত উপায়ের প্রয়োজন হয় তবে আপনি নীচের কোডটিকেও ভিত্তি হিসাবে ব্যবহার করতে পারেন।

যতক্ষণ আপনি প্রতিটি ফাংশন কল করার আগে 'প্রত্যাবর্তন' যুক্ত করেন, প্রতিশ্রুতির বর্ণনা দিয়ে থাকেন এবং এই উদাহরণটিকে পরবর্তী হিসাবে ভিত্তি হিসাবে ব্যবহার করেন then তারপর () ফাংশন কলটি পূর্ববর্তীটি শেষ হওয়ার পরে স্বতঃস্ফূর্তভাবে শুরু হবে:

getRidOfOlderShoutsPromise = () => {
    return readShoutsPromise('BEFORE')
    .then(() => {
        return deleteOlderShoutsPromise();
    })
    .then(() => {
        return readShoutsPromise('AFTER')
    })
    .catch(err => console.log(err.message));
}

deleteOlderShoutsPromise = () => {
    return new Promise ( (resolve, reject) => {
        console.log("in deleteOlderShouts");
        let d = new Date();
        let TwoMinuteAgo = d - 1000 * 90 ;
        All_Shouts.deleteMany({ dateTime: {$lt: TwoMinuteAgo}}, function(err) {
            if (err) reject();
            console.log("DELETED OLDs at "+d);
            resolve();        
        });
    });
}

readShoutsPromise = (tex) => {
    return new Promise( (resolve, reject) => {
        console.log("in readShoutsPromise -"+tex);
        All_Shouts
        .find({})
        .sort([['dateTime', 'ascending']])
        .exec(function (err, data){
            if (err) reject();
            let d = new Date();
            console.log("shouts "+tex+" delete PROMISE = "+data.length +"; date ="+d);
            resolve(data);
        });    
    });
}

0

প্রতিশ্রুতির ক্রমের জন্য অ্যারে পুশ এবং পপ পদ্ধতি ব্যবহার করা যেতে পারে। আপনার অতিরিক্ত ডেটার প্রয়োজন হলে আপনি নতুন প্রতিশ্রুতিগুলিও ঠেলে দিতে পারেন। এই কোডটি, আমি পৃষ্ঠাগুলির ক্রম লোড করতে প্রতিক্রিয়া অসীম লোডার ব্যবহার করব।

var promises = [Promise.resolve()];

function methodThatReturnsAPromise(page) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			console.log(`Resolve-${page}! ${new Date()} `);
			resolve();
		}, 1000);
	});
}

function pushPromise(page) {
	promises.push(promises.pop().then(function () {
		return methodThatReturnsAPromise(page)
	}));
}

pushPromise(1);
pushPromise(2);
pushPromise(3);


0

বেশিরভাগ উত্তরের মধ্যে সমস্ত প্রতিশ্রুতির ফলাফল স্বতন্ত্রভাবে অন্তর্ভুক্ত থাকে না, তাই যদি কেউ এই বিশেষ আচরণটির সন্ধান করে তবে এটি পুনরাবৃত্তি ব্যবহার করে একটি সম্ভাব্য সমাধান।

এটি এর স্টাইল অনুসরণ করে Promise.all:

  • .then()কলব্যাকের ফলাফলের অ্যারেটি ফিরিয়ে দেয়।

  • কিছু প্রতিশ্রুতি যদি ব্যর্থ হয় তবে তা .catch()কলব্যাকের সাথে সাথেই ফিরে আসবে ।

const promiseEach = (arrayOfTasks) => {
  let results = []
  return new Promise((resolve, reject) => {
    const resolveNext = (arrayOfTasks) => {
      // If all tasks are already resolved, return the final array of results
      if (arrayOfTasks.length === 0) return resolve(results)

      // Extract first promise and solve it
      const first = arrayOfTasks.shift()

      first().then((res) => {
        results.push(res)
        resolveNext(arrayOfTasks)
      }).catch((err) => {
        reject(err)
      })
    }
    resolveNext(arrayOfTasks)
  })
}

// Lets try it 😎

const promise = (time, shouldThrowError) => new Promise((resolve, reject) => {
  const timeInMs = time * 1000
  setTimeout(()=>{
    console.log(`Waited ${time} secs`)
    if (shouldThrowError) reject(new Error('Promise failed'))
    resolve(time)
  }, timeInMs)
})

const tasks = [() => promise(1), () => promise(2)]

promiseEach(tasks)
  .then((res) => {
    console.log(res) // [1, 2]
  })
  // Oops some promise failed
  .catch((error) => {
    console.log(error)
  })

tasksঅ্যারে ঘোষণা সম্পর্কে নোট :

এক্ষেত্রে নিম্নলিখিত নোটেশনটি ব্যবহার করা যেমন ব্যবহার করা সম্ভব নয় Promise.all:

const tasks = [promise(1), promise(2)]

এবং আমাদের ব্যবহার করতে হবে:

const tasks = [() => promise(1), () => promise(2)]

কারণটি হ'ল জাভাস্ক্রিপ্ট প্রতিশ্রুতি ঘোষণার পরে অবিলম্বে সম্পাদন শুরু করে। যদি আমরা এর মতো পদ্ধতি ব্যবহার করি তবে Promise.allএটি কেবলমাত্র তাদের সমস্তের অবস্থা fulfilledবা এটি পরীক্ষা করে rejectedকিন্তু এটি নিজেই নিষ্কাশন শুরু করে না। ব্যবহার () => promise()না করা পর্যন্ত আমরা কার্যকর করা বন্ধ করি।


0
(function() {
  function sleep(ms) {
    return new Promise(function(resolve) {
      setTimeout(function() {
        return resolve();
      }, ms);
    });
  }

  function serial(arr, index, results) {
    if (index == arr.length) {
      return Promise.resolve(results);
    }
    return new Promise(function(resolve, reject) {
      if (!index) {
        index = 0;
        results = [];
      }
      return arr[index]()
        .then(function(d) {
          return resolve(d);
        })
        .catch(function(err) {
          return reject(err);
        });
    })
      .then(function(result) {
        console.log("here");
        results.push(result);
        return serial(arr, index + 1, results);
      })
      .catch(function(err) {
        throw err;
      });
  }

  const a = [5000, 5000, 5000];

  serial(a.map(x => () => sleep(x)));
})();

এখানে কীটি আপনি ঘুমের ফাংশনটি কল করেন তা এখানে। আপনাকে ফাংশনগুলির একটি অ্যারে পাস করতে হবে যা প্রতিশ্রুতির অ্যারের পরিবর্তে নিজেই প্রতিশ্রুতি দেয়।


-1

এটি স্পেকস.সেক্সেন্স প্রয়োগের উপর ভিত্তি করে গতিশীল / অসীম সিকোয়েন্সগুলিকে সমর্থন করে আরও জেনেরিক উপায়ে প্রতিশ্রুতির ক্রমটি কীভাবে প্রক্রিয়াকরণ করা যায় তার প্রসারিত করা :

var $q = require("q");
var spex = require('spex')($q);

var files = []; // any dynamic source of files;

var readFile = function (file) {
    // returns a promise;
};

function source(index) {
    if (index < files.length) {
        return readFile(files[index]);
    }
}

function dest(index, data) {
    // data = resolved data from readFile;
}

spex.sequence(source, dest)
    .then(function (data) {
        // finished the sequence;
    })
    .catch(function (error) {
        // error;
    });

এই সমাধানটি কোনও আকারের ক্রমগুলির সাথেই কাজ করবে না, তবে আপনি সহজেই এতে ডেটা থ্রোটলিং যোগ করতে এবং এতে ভারসাম্য লোড করতে পারেন।

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