मुझे छवियों के किसी ऑब्जेक्ट के माध्यम से लूप करने और प्रत्येक छवि पर एक समय में एक एसिंक्रोनस फ़ंक्शन करने में सक्षम होना चाहिए। अगर मैं इमेज ऑब्जेक्ट को किसी ऐरे में कनवर्ट करता हूं तो मेरे पास यह काम करने का तरीका है, लेकिन मैं इसे for...in लूप के साथ करना चाहता हूं ताकि मैं इमेज कीज़ का भी उपयोग कर सकूं। मुझे भी अंत में एक क्रिया करने में सक्षम होना चाहिए जैसा कि मैं वर्तमान में हूं।

var images = {
  ABD: '1464685684713583388647.jpg',
  ABY: '1457524543088191607099.jpg',
  ADV: '1478877365443818880647.jpg',
  AFD: '1457527861824290195088.jpg',
}
var imagesArray = Object.values(images);
var len = imagesArray.length;

function asynchronousImageFunction (key, image, onSuccess, onFail) {
  setTimeout(function () {
    console.log(key);
    console.log(image);
    onSuccess();
  }, Math.random() * 1000)
}

(function loop(i) {
  if (i < len) {
    new Promise(function (resolve, reject) {
      asynchronousImageFunction ('key', imagesArray[i], resolve, reject);
    }).then(loop.bind(null, i+1));
  } else {
    console.log('end');
  }
})(0);

आदेश महत्वपूर्ण नहीं है, लेकिन उन्हें एक के बाद एक कॉल करना है, और एक पूर्ण या समाप्त कॉल करना भी आवश्यक है। मैं बस इसके चारों ओर अपना सिर नहीं घुमा सकता, क्या कोई मदद कर सकता है?

0
juliusbangert 3 अप्रैल 2018, 21:04

3 जवाब

सबसे बढ़िया उत्तर

ऐसा करने के लिए reduce का उपयोग करना एक अच्छा तरीका है। आप कुंजी/मान जोड़े को Object.entries के साथ पास कर सकते हैं

var images = {
  ABD: '1464685684713583388647.jpg',
  ABY: '1457524543088191607099.jpg',
  ADV: '1478877365443818880647.jpg',
  AFD: '1457527861824290195088.jpg',
}

function asynchronousImageFunction(key, image, onSuccess, onFail) {
  setTimeout(function() {
    console.log(key);
    console.log(image);
    onSuccess();
  }, 1000)
}

Object.entries(images).reduce((a, [key, value]) => {
  return a.then(() => new Promise((resolve, reject) => {
    asynchronousImageFunction(key, value, resolve, reject);
  }))}, Promise.resolve())
.then(() => console.log("end"))

यदि, दूसरी ओर, आपके async फ़ंक्शन ने अपना वादा वापस कर दिया है, तो यह आंखों पर थोड़ा आसान होगा:

var images = {
  ABD: '1464685684713583388647.jpg',
  ABY: '1457524543088191607099.jpg',
  ADV: '1478877365443818880647.jpg',
  AFD: '1457527861824290195088.jpg',
}

function asynchronousImageFunction(key, image, onSuccess, onFail) {
  return new Promise((resolve, reject) => {
    setTimeout(function() {
      console.log(key);
      console.log(image);
      resolve();
    }, 1000)
  })
}

Object.entries(images).reduce((a, [key, value]) => 
  a.then(() => asynchronousImageFunction(key, value))
  , Promise.resolve())
  .then(() => console.log("end"))
2
Mark M 3 अप्रैल 2018, 18:30

आप वास्तव में for...in के साथ ऐसा करने में सक्षम नहीं होंगे। for...in और for...of जैसे लूप्स को अगली पुनरावृत्ति शुरू करने से पहले एसिंक्रोनस ईवेंट की प्रतीक्षा करने का निर्देश नहीं दिया जा सकता है।

आपको जो करना है वह कुछ ऐसा लागू करना है जो वांछित लूप की तरह व्यवहार करता है, लेकिन करता है async ईवेंट की प्रतीक्षा करता है। आपने जो किया है वह एक सरणी पर for...of जैसा व्यवहार करता है। आप कुछ ऐसा करके चाबियां उपलब्ध करा सकते हैं जैसे Mark_M ने वर्णन किया है।

हालांकि, यह एक बहुत ही सामान्य ऑपरेशन है, और पुस्तकालयों जैसे async में सारगर्भित (कई अन्य अतुल्यकालिक संचालन के साथ) किया गया है , जिससे आप इस झुंझलाहट को छोड़ सकते हैं और बस वही लिख सकते हैं जो आप चाहते हैं:

var images = {
  ABD: '1464685684713583388647.jpg',
  ABY: '1457524543088191607099.jpg',
  ADV: '1478877365443818880647.jpg',
  AFD: '1457527861824290195088.jpg',
}

function asynchronousImageFunction(key, image, callback) {
  setTimeout(function () {
    console.log(key);
    console.log(image);
    // Usual convention of `async` callbacks. The first argument should be
    // null/undefined/omitted if no error occurred:
    callback();
    // If there was an error, you would instead do this:
    // callback(err);
  }, Math.random() * 1000)
}

async.eachOfSeries(images, function(image, key, callback) {
    asynchronousImageFunction(key, image, callback);
}, function(err) {
    console.log('end');
});

Async.eachOfSeries के दस्तावेज़ यहां देखे जा सकते हैं।

आप देखेंगे कि मैंने यहां एक प्रॉमिस का उपयोग नहीं किया है। यह काफी हद तक इसलिए है क्योंकि आपका asynchronousImageFunction कॉलबैक-आधारित है, जैसा कि async लाइब्रेरी ही है। एसिंक कोड से निपटने के दौरान मेरी सलाह है कि शैलियों के बीच अक्सर आगे और पीछे फ्लिप न करने का प्रयास करें, या सामान हेला भ्रमित हो जाता है।

यदि आप अपने वातावरण में CommonJS मॉड्यूल को काम करने में सक्षम हैं, तो async के वादे-आधारित संस्करण हैं। मेरे पसंदीदा में से एक यहां है। इसके साथ, आप लूप को स्वयं वादा-आधारित बना सकते हैं:

const pasync = require('pasync');

var images = {
  ABD: '1464685684713583388647.jpg',
  ABY: '1457524543088191607099.jpg',
  ADV: '1478877365443818880647.jpg',
  AFD: '1457527861824290195088.jpg',
}

function asynchronousImageFunction(key, image) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(key);
            console.log(image);
            resolve();
        }, Math.random() * 1000);
    });
}

pasync.eachOfSeries(
    images,
    (image, key) => asynchronousImageFunction(key, image)
)
    .then(() => {
        console.log('end');
    });
0
sripberger 3 अप्रैल 2018, 18:55

अगर आपको भी चाबियों का उपयोग करने की आवश्यकता है तो Object.values के बजाय बस Object.keys या Object.entries का उपयोग करें।

var imageKeysArray = Object.key(images);
var len = imagesArray.length;
(function loop(i) {
  if (i < len) {
    var key = imageKeysArray[i];
    var value = images[key];
    asynchronousImageFunction(key, value).then(loop.bind(null, i+1));
  } else {
    console.log('end');
  }
})(0);

ध्यान दें कि new Promise रैपर सीधे setTimeout कॉल के आसपास, asynchronousImageFunction के अंदर होना चाहिए; इससे उपयोग करना आसान हो जाता है और आपको कम कॉलबैक पास करने की आवश्यकता होती है।

विकल्प जो आपको वास्तविक for … in लूप का उपयोग करने देगा async/await सिंटैक्स है:

(async function loop() {
  for (const key in images)
    await asynchronousImageFunction(key, images[key]);
  console.log("end");
})();
0
Bergi 3 अप्रैल 2018, 18:31