জাভাস্ক্রিপ্ট, নোড.জেএস: অ্যারে.ফোর প্রতিটি অ্যাসিনক্রোনাস?


378

Array.forEachজাভাস্ক্রিপ্টের নেটিভ বাস্তবায়ন সম্পর্কে আমার একটি প্রশ্ন রয়েছে : এটি কি অ্যাসিঙ্ক্রোনালি আচরণ করে? উদাহরণস্বরূপ, যদি আমি কল করি:

[many many elements].forEach(function () {lots of work to do})

এটি কি অবরুদ্ধ হবে?


উত্তর:


392

না, এটি ব্লক করছে। অ্যালগরিদমের স্পেসিফিকেশন একবার দেখুন ।

তবে সম্ভবত বাস্তবায়ন বোঝার জন্য আরও সহজ এমডিএন দেওয়া আছে :

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in t)
        fun.call(thisp, t[i], i, t);
    }
  };
}

আপনার যদি প্রতিটি উপাদানটির জন্য প্রচুর কোড চালাতে হয় তবে আপনার আলাদা পদ্ধতির ব্যবহার বিবেচনা করা উচিত:

function processArray(items, process) {
    var todo = items.concat();

    setTimeout(function() {
        process(todo.shift());
        if(todo.length > 0) {
            setTimeout(arguments.callee, 25);
        }
    }, 25);
}

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

processArray([many many elements], function () {lots of work to do});

এটি তখন অবরুদ্ধ হবে। উদাহরণটি উচ্চ পারফরম্যান্স জাভাস্ক্রিপ্ট থেকে নেওয়া হয়েছে ।

অন্য বিকল্প ওয়েব কর্মী হতে পারে ।


37
আপনি যদি নোড.জেএস ব্যবহার করছেন তবে প্রক্রিয়া.নেক্সটটিক ব্যবহারের বিষয়টিও বিবেচনা করুন setTimeout পরিবর্তে
মার্সেলো Bastea-উচ্চনিনাদী

28
প্রযুক্তিগতভাবে, forEach "ব্লকিং" নয়, সিপিইউ কখনই ঘুমায় না। এটি সিঙ্ক্রোনাস এবং সিপিইউ-আবদ্ধ, যখন আপনি নোড অ্যাপ্লিকেশনগুলিতে প্রতিক্রিয়াশীল হওয়ার প্রত্যাশা করবেন তখন এটি "ব্লকিং" এর মতো অনুভব করতে পারে।
ডেভ ডপসন 17

3
অ্যাসিঙ্ক সম্ভবত এখানে আরও উপযুক্ত সমাধান হতে পারে (বাস্তবে কাউকে পোস্ট হিসাবে দেখেছি উত্তর হিসাবে!)।
জেমস

6
আমি এই উত্তরটি বিশ্বাস করেছিলাম, তবে এটি কিছু ক্ষেত্রে ভুল বলে মনে হচ্ছে। উদাহরণস্বরূপ বিবৃতিগুলিতে ব্লক forEachকরে নাawait এবং আপনার পরিবর্তে একটি forলুপ ব্যবহার করা উচিত : stackoverflow.com/questions/37962880/…
রিচার্ড

3
@ রিচার্ড: অবশ্যই আপনি কেবল awaitঅভ্যন্তরীণ asyncফাংশনগুলি ব্যবহার করতে পারেন । কিন্তু forEachঅ্যাসিঙ্ক ফাংশনগুলি কী তা জানেন না। মনে রাখবেন যে অ্যাসিঙ্ক ফাংশনগুলি কেবল একটি প্রতিশ্রুতি ফেরত ফাংশন। আপনি কি forEachকলব্যাক থেকে ফিরে কোন প্রতিশ্রুতি সামলানোর আশা করবেন? forEachকলব্যাক থেকে রিটার্ন মানটিকে সম্পূর্ণ উপেক্ষা করে। এটি কেবলমাত্র একটি অ্যাসিঙ্ক কলব্যাক পরিচালনা করতে সক্ষম হবে যদি এটি নিজেই অ্যাসিঙ্ক থাকে।
ফেলিক্স ক্লিং

80

আপনার যদি এর মতো একটি অ্যাসিনক্রোনাস-বান্ধব সংস্করণ Array.forEachএবং অনুরূপ প্রয়োজন হয় তবে সেগুলি নোড.জেএস এর ' অ্যাসিঙ্ক ' মডিউলটিতে উপলব্ধ: http://github.com/caolan/async ... বোনাস হিসাবে এই মডিউলটি ব্রাউজারেও কাজ করে ।

async.each(openFiles, saveFile, function(err){
    // if any of the saves produced an error, err would equal that error
});

2
যদি আপনাকে নিশ্চিত করতে হয় যে একবারে কেবলমাত্র এক আইটেমের জন্য (সংগ্রহের ক্রমে) অ্যাসিঙ্ক অপিয়ারেশন চালিত হয় , তবে আপনাকে অবশ্যই তার eachSeriesপরিবর্তে ব্যবহার করতে হবে।
ম্যাটপপ

@ জন কেনেডি আমি আপনাকে আগে দেখেছি!
এক্সএমএল

16

নোডে সত্যিই ভারী গণনা করার জন্য একটি সাধারণ প্যাটার্ন রয়েছে যা আপনার জন্য প্রযোজ্য হতে পারে ...

নোড একক থ্রেডেড (ইচ্ছাকৃত ডিজাইনের পছন্দ হিসাবে দেখুন নোড.জেএস কি? ); এর অর্থ এটি কেবল একটি একক কোর ব্যবহার করতে পারে। আধুনিক বাক্সগুলিতে 8, 16 বা আরও বেশি কোর রয়েছে, সুতরাং এটি 90% + মেশিনকে অলস রাখতে পারে। একটি REST পরিষেবার সাধারণ প্যাটার্নটি হ'ল কোর প্রতি এক নোড প্রক্রিয়া চালিত করা এবং এগুলিকে http://nginx.org/ এর মতো স্থানীয় লোড ব্যালান্সারের পিছনে রাখা ।

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

উদাহরণ স্বরূপ:

var child_process = প্রয়োজনীয় ('চাইল্ড_প্রসেস');
ফাংশন রান_ইনচাইল্ড (অ্যারে, সিবি) {
    var প্রক্রিয়া = চাইল্ড_প্রসেস.এক্সেক ('নোড লিবিফএন.জেএস', ফাংশন (ত্রুটি, স্টডআউট, স্টার্ডার)
        var আউটপুট = JSON.parse (stdout);
        সিবি (এরর, আউটপুট);
    });
    প্রক্রিয়া.স্টদিন.উইরাইট (JSON.stringify (অ্যারে), 'utf8');
    process.stdin.end ();
}

11
কেবল পরিষ্কার করার জন্য ... নোড একক থ্রেডেড নয়, তবে আপনার জাভাস্ক্রিপ্টের সম্পাদন। আইও এবং কী আলাদা থ্রেডে চলবে না।
ব্র্যাড

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

4
ঠিক আছে, আমি কেবল স্পষ্ট করছি কারণ ধারণাটি অনেকগুলিকে বিভ্রান্ত করেছে।
ব্র্যাড

6

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


5

সম্পাদনা 2018-10-11: দেখে মনে হচ্ছে একটি ভাল সুযোগ আছে মান নীচে বর্ণিত মধ্য দিয়ে যেতে পারে না, বিবেচনা মত pipelineing একটি বিকল্প (ঠিক একই আচরণ করে না কিন্তু পদ্ধতি একই জমিদারি বাস্তবায়িত হতে পারে) হিসাবে।

এ কারণেই আমি এস 7 সম্পর্কে উত্সাহিত, ভবিষ্যতে আপনি নীচের কোডটির মতো কিছু করতে সক্ষম হবেন (কিছু চশমা সম্পূর্ণ নয় তাই সাবধানতার সাথে ব্যবহার করুন, আমি এটি আপডেট রাখার চেষ্টা করব)। তবে মূলত: নতুন :: বাইন্ড অপারেটরটি ব্যবহার করে আপনি কোনও অবজেক্টে কোনও পদ্ধতি চালাতে সক্ষম হবেন যেন বস্তুর প্রোটোটাইপটিতে কোনও পদ্ধতি রয়েছে। উদাহরণস্বরূপ [অবজেক্ট] :: [পদ্ধতি] যেখানে আপনি সাধারণত [অবজেক্ট] কল করবেন [[অবজেক্টস ম্যাথড]

আজ (24-জুলাই -16) এটি করার জন্য দ্রষ্টব্য এবং নিম্নলিখিত ব্রাউজারগুলিতে এটি কাজ করার জন্য আপনাকে নীচের কার্যকারিতাটির জন্য আপনার কোডটি স্থানান্তর করতে হবে: আমদানি / রফতানি , তীর ফাংশন , প্রতিশ্রুতি , অ্যাসিঙ্ক / অ্যাওয়েট এবং সর্বাধিক গুরুত্বপূর্ণভাবে ফাংশন বাইন্ড । নিচে যদি nessesary শুধুমাত্র ফাংশন বেঁধে ব্যবহার করতে modfied যেতে পারে কোড, সব এই কার্যকারিতা সুন্দরভাবে প্রাপ্তিসাধ্য আজ ব্যবহার করা Babel

আপনারকোড.জেএস (যেখানে ' প্রচুর কাজ করতে হবে ' অবশ্যই একটি প্রতিশ্রুতি ফিরিয়ে আনতে হবে, অ্যাসিনক্রোনাস কাজ সম্পন্ন হওয়ার পরে এটি সমাধান করতে হবে))

import { asyncForEach } from './ArrayExtensions.js';

await [many many elements]::asyncForEach(() => lots of work to do);

ArrayExtensions.js

export function asyncForEach(callback)
{
    return Promise.resolve(this).then(async (ar) =>
    {
        for(let i=0;i<ar.length;i++)
        {
            await callback.call(ar, ar[i], i, ar);
        }
    });
};

export function asyncMap(callback)
{
    return Promise.resolve(this).then(async (ar) =>
    {
        const out = [];
        for(let i=0;i<ar.length;i++)
        {
            out[i] = await callback.call(ar, ar[i], i, ar);
        }
        return out;
    });
};

1

এটি তৃতীয় পক্ষের libs প্রয়োজন ছাড়াই ব্যবহার করার জন্য একটি সংক্ষিপ্ত অ্যাসিনক্রোনাস ফাংশন

Array.prototype.each = function (iterator, callback) {
    var iterate = function () {
            pointer++;
            if (pointer >= this.length) {
                callback();
                return;
            }
            iterator.call(iterator, this[pointer], iterate, pointer);
    }.bind(this),
        pointer = -1;
    iterate(this);
};

এই অ্যাসিক্রোনাস কেমন? আফাইক # কল সব সঙ্গে সঙ্গে কার্যকর হবে?
জিলস উইলিয়ামস

1
অবশ্যই অবিলম্বে, তবে সমস্ত পুনরাবৃত্তি কখন শেষ হবে তা জানতে আপনার কলব্যাক ফাংশন রয়েছে। এখানে "পুনরায়" আর্গুমেন্টটি কলব্যাক সহ নোড-স্টাইলের অ্যাসিঙ্ক ফাংশন। এটি async.each পদ্ধতির অনুরূপ
রাক্স ওয়ানটার

3
আমি দেখতে পাচ্ছি না যে এটি অ্যাসিঙ্ক। কল বা প্রয়োগ সিঙ্ক্রোনাস। একটি কলব্যাক থাকা
এ্যাসিঙ্ক

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

0

প্রতিটি লুপের জন্য সহজ অ্যাসিনক্রোনাসের জন্য এনপিএমে একটি প্যাকেজ রয়েছে ।

var forEachAsync = require('futures').forEachAsync;

// waits for one request to finish before beginning the next 
forEachAsync(['dogs', 'cats', 'octocats'], function (next, element, index, array) {
  getPics(element, next);
  // then after all of the elements have been handled 
  // the final callback fires to let you know it's all done 
  }).then(function () {
    console.log('All requests have finished');
});

এছাড়াও AllAsync এর জন্য আরেকটি প্রকরণ


0

এমনকি সমাধানটিরও এভাবে কোড করা সম্ভব উদাহরণস্বরূপ:

 var loop = function(i, data, callback) {
    if (i < data.length) {
        //TODO("SELECT * FROM stackoverflowUsers;", function(res) {
            //data[i].meta = res;
            console.log(i, data[i].title);
            return loop(i+1, data, errors, callback);
        //});
    } else {
       return callback(data);
    }
};

loop(0, [{"title": "hello"}, {"title": "world"}], function(data) {
    console.log("DONE\n"+data);
});

অন্যদিকে, এটি "ফর" এর চেয়ে অনেক ধীর গতির।

অন্যথায়, চমৎকার অ্যাসিঙ্ক লাইব্রেরি এটি করতে পারে: https://caolan.github.io/async/docs.html#each


0

এটি পরীক্ষা করার জন্য আপনি চালাতে পারেন এমন একটি ছোট উদাহরণ এখানে:

[1,2,3,4,5,6,7,8,9].forEach(function(n){
    var sum = 0;
    console.log('Start for:' + n);
    for (var i = 0; i < ( 10 - n) * 100000000; i++)
        sum++;

    console.log('Ended for:' + n, sum);
});

এটি এর মতো কিছু তৈরি করবে (যদি এটি খুব কম / বেশি সময় নেয় তবে পুনরাবৃত্তির সংখ্যা বৃদ্ধি / হ্রাস করে):

(index):48 Start for:1
(index):52 Ended for:1 900000000
(index):48 Start for:2
(index):52 Ended for:2 800000000
(index):48 Start for:3
(index):52 Ended for:3 700000000
(index):48 Start for:4
(index):52 Ended for:4 600000000
(index):48 Start for:5
(index):52 Ended for:5 500000000
(index):48 Start for:6
(index):52 Ended for:6 400000000
(index):48 Start for:7
(index):52 Ended for:7 300000000
(index):48 Start for:8
(index):52 Ended for:8 200000000
(index):48 Start for:9
(index):52 Ended for:9 100000000
(index):45 [Violation] 'load' handler took 7285ms

আপনি async.foreach বা অন্য কোনও সমান্তরাল পদ্ধতি লিখলেও এটি ঘটবে। কারণ লুপটি কোনও আইও প্রক্রিয়া নয় নোডেজ সর্বদা এটি সুসংগতভাবে করবে।
সুধাংশু গৌড়

-2

ব্যবহারের Promise.each এর Bluebird গ্রন্থাগার।

Promise.each(
Iterable<any>|Promise<Iterable<any>> input,
function(any item, int index, int length) iterator
) -> Promise

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

যদি সমস্ত পুনরাবৃত্তি সাফল্যের সাথে সমাধান করা হয় তবে Promise.each মূল অ্যারেটি অবিচলিতভাবে সমাধান করে । যাইহোক, যদি এক পুনরাবৃত্তির প্রত্যাখ্যান বা ত্রুটি, Promise.each মৃত্যুদন্ড অবিলম্বে ceases আর কোনও পুনরাবৃত্তিও প্রক্রিয়া নেই। ত্রুটি বা প্রত্যাখ্যাত মানটি মূল অ্যারের পরিবর্তে এই ক্ষেত্রে ফিরে আসে।

এই পদ্ধতিটি পার্শ্ব প্রতিক্রিয়াগুলির জন্য ব্যবহার করা বোঝায়।

var fileNames = ["1.txt", "2.txt", "3.txt"];

Promise.each(fileNames, function(fileName) {
    return fs.readFileAsync(fileName).then(function(val){
        // do stuff with 'val' here.  
    });
}).then(function() {
console.log("done");
});
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.