জাভাস্ক্রিপ্টে কিছু অ্যাসিনক্রোনাস কাজ সম্পূর্ণ হওয়ার অপেক্ষা রাখার সহজ উপায়?


112

আমি কিছু মংডব সংগ্রহ সংগ্রহ করতে চাই, তবে এটি একটি অ্যাসিনক্রোনাস কাজ। কোডটি হবে:

var mongoose = require('mongoose');

mongoose.connect('mongo://localhost/xxx');

var conn = mongoose.connection;

['aaa','bbb','ccc'].forEach(function(name){
    conn.collection(name).drop(function(err) {
        console.log('dropped');
    });
});
console.log('all dropped');

কনসোলটি প্রদর্শন করে:

all dropped
dropped
dropped
dropped

all droppedসমস্ত সংগ্রহ বাদ দেওয়ার পরে মুদ্রণ করা হবে তা নিশ্চিত করার সহজ উপায় কী ? কোডটি সরল করতে যে কোনও তৃতীয় পক্ষের ব্যবহার করা যেতে পারে।

উত্তর:


92

আপনি দেখতে পাচ্ছেন mongooseতাই আপনি সার্ভার-সাইড জাভাস্ক্রিপ্টের কথা বলছেন about সেক্ষেত্রে আমি async মডিউলটি এবং ব্যবহারটি দেখার পরামর্শ দিই async.parallel(...)। আপনি এই মডিউলটি সত্যিই সহায়ক হিসাবে খুঁজে পাবেন - আপনি যে সমস্যার সাথে লড়াই করছেন এটি সমাধানের জন্য এটি তৈরি করা হয়েছিল। আপনার কোডটি এর মতো দেখতে পারে

var async = require('async');

var calls = [];

['aaa','bbb','ccc'].forEach(function(name){
    calls.push(function(callback) {
        conn.collection(name).drop(function(err) {
            if (err)
                return callback(err);
            console.log('dropped');
            callback(null, name);
        });
    }
)});

async.parallel(calls, function(err, result) {
    /* this code will run after all calls finished the job or
       when any of the calls passes an error */
    if (err)
        return console.log(err);
    console.log(result);
});

এটির সাথে ... forEach পদ্ধতিটি async হয়। সুতরাং যদি এখানে অবজেক্টের তালিকাটি বিশদ 3 টির চেয়ে দীর্ঘ ছিল, তবে এটি কি এমন হতে পারে না যে যখন async.parallel (কল, ফাংশন (ত্রুটি, ফলাফল) কল করা হয় তখনও মূল তালিকার সমস্ত ফাংশন থাকে না?
মার্টিন বিবি

5
@ মার্টিনবিবি forEachসিঙ্ক্রোনাস। এখানে একবার দেখুন: বিকাশকারী.মোজিলা.আর.ইন- ইউএস / ডকস / ওয়েব / জাভা স্ক্রিপ্ট / রেফারেন্স /… forEachনীচে বাস্তবায়ন রয়েছে । কলব্যাক সহ সমস্ত কিছুই অ্যাসিনক্রোনাস নয়।
freakish

2
রেকর্ডের জন্য, async একটি ব্রাউজারেও ব্যবহার করা যেতে পারে।
এরউইন ওয়েসেলস

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

3
@ ঘেরট 85 না, পরিভাষাগুলিতে কোনও ভুল নেই। কলব্যাক হ'ল এমন কোনও এক্সিকিউটেবল কোড যা অন্য কোডের আর্গুমেন্ট হিসাবে পাস হয়ে যায় এবং আশা করা হয় যে এটি কোনও সময়ে কার্যকর করা হবে। এটা স্ট্যান্ডার্ড সংজ্ঞা। এবং এটিকে সিঙ্ক্রোনাস বা অ্যাসিক্রোনোলজিকভাবে বলা যেতে পারে। এটি দেখুন: en.wikedia.org/wiki/Callback_(computer_programming)
freakish

128

প্রতিশ্রুতি ব্যবহার করুন ।

var mongoose = require('mongoose');

mongoose.connect('your MongoDB connection string');
var conn = mongoose.connection;

var promises = ['aaa', 'bbb', 'ccc'].map(function(name) {
  return new Promise(function(resolve, reject) {
    var collection = conn.collection(name);
    collection.drop(function(err) {
      if (err) { return reject(err); }
      console.log('dropped ' + name);
      resolve();
    });
  });
});

Promise.all(promises)
.then(function() { console.log('all dropped)'); })
.catch(console.error);

এটি প্রতিটি সংগ্রহের ড্রপ করে, প্রতিটিের পরে "ফেলে দেওয়া" মুদ্রণ করে এবং তারপরে সম্পূর্ণ হয়ে গেলে "সমস্ত ড্রপ" মুদ্রণ করে। যদি কোনও ত্রুটি দেখা দেয় তবে এটি প্রদর্শিত হয় stderr


পূর্ববর্তী উত্তর (প্রতিশ্রুতিগুলির জন্য নোডের দেশীয় সমর্থন এটি পূর্ব-তারিখগুলি):

কিউ প্রতিশ্রুতি বা ব্লুবার্ড প্রতিশ্রুতি ব্যবহার করুন ।

সঙ্গে প্রশ্ন :

var Q = require('q');
var mongoose = require('mongoose');

mongoose.connect('your MongoDB connection string');
var conn = mongoose.connection;

var promises = ['aaa','bbb','ccc'].map(function(name){
    var collection = conn.collection(name);
    return Q.ninvoke(collection, 'drop')
      .then(function() { console.log('dropped ' + name); });
});

Q.all(promises)
.then(function() { console.log('all dropped'); })
.fail(console.error);

সঙ্গে Bluebird :

var Promise = require('bluebird');
var mongoose = Promise.promisifyAll(require('mongoose'));

mongoose.connect('your MongoDB connection string');
var conn = mongoose.connection;

var promises = ['aaa', 'bbb', 'ccc'].map(function(name) {
  return conn.collection(name).dropAsync().then(function() {
    console.log('dropped ' + name);
  });
});

Promise.all(promises)
.then(function() { console.log('all dropped'); })
.error(console.error);

1
প্রতিশ্রুতি হয় উপায়। ব্লুবার্ড হ'ল একটি প্রতিশ্রুতি পাঠাগার যা এটি কার্য সম্পাদন-সমালোচনামূলক কোড এ থাকলে ভাল কাজ করবে। এটি একটি ড্রপ-ইন প্রতিস্থাপন হওয়া উচিত। শুধু ব্যবহার require('bluebird')
weiyin

আমি একটি ব্লুবার্ড উদাহরণ যুক্ত করেছি। এটি একটু আলাদা কারণ ব্লুবার্ড ব্যবহারের সর্বোত্তম উপায়টি promisifyAllবৈশিষ্ট্যটি ব্যবহার করা ।
Nate

প্রোমিসিফএল কীভাবে কাজ করে তার কোনও ধারণা..আমি ডকস পড়েছি তবে আমি তা পাই না যে এটি প্যারামিটারগুলি পছন্দ না করে এমন ফাংশনগুলি কীভাবে পরিচালনা করে function abc(data){, কারণ এটি function abc(err, callback){...মূলত আমি পছন্দ করি না যে সমস্ত ফাংশনগুলি প্রথম প্যারাম হিসাবে ত্রুটি নেয় এবং ২ য় প্যারাম হিসাবে কলব্যাক হয়
মুহাম্মদ উমার

@ মুহাম্মাদউমার ব্লুবার্ডজেএসএস
নট

মোংগোডিবি ড্রাইভারও প্রতিশ্রুতি সমর্থন করার পরে অনেক দিন হয়ে গেছে। এর সুবিধা নিতে আপনি কি নিজের উদাহরণ আপডেট করতে পারবেন? .map(function(name) { return conn.collection(name).drop() })
djanowski

21

এটি করার উপায় হ'ল কার্যগুলি একটি কলব্যাক যা কোনও ভাগ করা কাউন্টারকে আপডেট করে pass যখন ভাগ করা কাউন্টার শূন্যে পৌঁছে যায় আপনি জানেন যে সমস্ত কাজ শেষ হয়েছে তাই আপনি আপনার স্বাভাবিক প্রবাহটি চালিয়ে যেতে পারেন।

var ntasks_left_to_go = 4;

var callback = function(){
    ntasks_left_to_go -= 1;
    if(ntasks_left_to_go <= 0){
         console.log('All tasks have completed. Do your stuff');
    }
}

task1(callback);
task2(callback);
task3(callback);
task4(callback);

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


এটি প্রয়োগ করা সবচেয়ে সহজ নাও হতে পারে তবে আমি সত্যিই এমন উত্তর দেখতে পছন্দ করি যার জন্য বাহ্যিক মডিউলগুলির প্রয়োজন হয় না। ধন্যবাদ!
কাউন্টারবাইজ করা

8

@ ফ্রেইকিশ উত্তরের উপর প্রসারিত করে, অ্যাসিঙ্ক প্রতিটি পদ্ধতি প্রয়োগ করে যা আপনার ক্ষেত্রে বিশেষভাবে উপযুক্ত বলে মনে হয়:

var async = require('async');

async.each(['aaa','bbb','ccc'], function(name, callback) {
    conn.collection(name).drop( callback );
}, function(err) {
    if( err ) { return console.log(err); }
    console.log('all dropped');
});

আইএমএইচও, এটি কোডটিকে আরও কার্যকর এবং আরও সুগঠিত করে তোলে। আমি অপসারণের স্বাধীনতা নিয়েছি console.log('dropped')- আপনি যদি এটি চান তবে এটি ব্যবহার করুন পরিবর্তে:

var async = require('async');

async.each(['aaa','bbb','ccc'], function(name, callback) {
    // if you really want the console.log( 'dropped' ),
    // replace the 'callback' here with an anonymous function
    conn.collection(name).drop( function(err) {
        if( err ) { return callback(err); }
        console.log('dropped');
        callback()
    });
}, function(err) {
    if( err ) { return console.log(err); }
    console.log('all dropped');
});

5

আমি বাহ্যিক bণপত্র ছাড়াই এটি করি:

var yourArray = ['aaa','bbb','ccc'];
var counter = [];

yourArray.forEach(function(name){
    conn.collection(name).drop(function(err) {
        counter.push(true);
        console.log('dropped');
        if(counter.length === yourArray.length){
            console.log('all dropped');
        }
    });                
});

4

সমস্ত উত্তর বেশ পুরানো। ২০১৩ সালের শুরু থেকে মঙ্গুজ সকল প্রশ্নের জন্য ধীরে ধীরে প্রতিশ্রুতিগুলি সমর্থন করা শুরু করেছিল , তাই আমার অনুমানের অনুসারে প্রয়োজনীয় ক্রমে বেশ কয়েকটি এসিঙ্ক কলগুলি গঠনের প্রস্তাবিত উপায় এটিই হবে।


0

সঙ্গে deferred(অন্য প্রতিশ্রুতি / বিলম্বিত বাস্তবায়ন) আপনি করতে পারেন:

// Setup 'pdrop', promise version of 'drop' method
var deferred = require('deferred');
mongoose.Collection.prototype.pdrop =
    deferred.promisify(mongoose.Collection.prototype.drop);

// Drop collections:
deferred.map(['aaa','bbb','ccc'], function(name){
    return conn.collection(name).pdrop()(function () {
      console.log("dropped");
    });
}).end(function () {
    console.log("all dropped");
}, null);

0

আপনি যদি ব্যাবেল বা এই জাতীয় পরিবহন ব্যবহার করে এবং অ্যাসিঙ্ক / অপেক্ষায় থাকেন তবে আপনি করতে পারেন:

function onDrop() {
   console.log("dropped");
}

async function dropAll( collections ) {
   const drops = collections.map(col => conn.collection(col).drop(onDrop) );
   await drops;
   console.log("all dropped");
}

আপনি কোনও কলব্যাক পাস করতে পারবেন না drop()এবং কোনও প্রতিশ্রুতি ফেরানোর প্রত্যাশা করতে পারবেন না । আপনি দয়া করে এই উদাহরণটি ঠিক করে মুছে ফেলতে পারেন onDrop?
djanowski
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.