অ্যাসিঙ্ক ফাংশন + অপেক্ষা + সেটটাইমআউট এর সংমিশ্রণ


305

আমি নতুন অ্যাসিঙ্ক বৈশিষ্ট্যগুলি ব্যবহার করার চেষ্টা করছি এবং আমি আশা করি আমার সমস্যা সমাধান করা ভবিষ্যতে অন্যদের সহায়তা করবে। এটি আমার কোড যা কাজ করছে:

  async function asyncGenerator() {
    // other code
    while (goOn) {
      // other code
      var fileList = await listFiles(nextPageToken);
      var parents = await requestParents(fileList);
      // other code
    }
    // other code
  }

  function listFiles(token) {
    return gapi.client.drive.files.list({
      'maxResults': sizeResults,
      'pageToken': token,
      'q': query
    });
  }

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

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

  async function asyncGenerator() {
    // other code
    while (goOn) {
      // other code
      var fileList = await sleep(listFiles, nextPageToken);
      var parents = await requestParents(fileList);
      // other code
    }
    // other code
  }

  function listFiles(token) {
    return gapi.client.drive.files.list({
      'maxResults': sizeResults,
      'pageToken': token,
      'q': query
    });
  }

  async function sleep(fn, par) {
    return await setTimeout(async function() {
      await fn(par);
    }, 3000, fn, par);
  }

আমি ইতিমধ্যে কিছু বিকল্প ব্যবহার করে দেখেছি: গ্লোবাল ভেরিয়েবলে প্রতিক্রিয়া সঞ্চয় করে ঘুমের ফাংশন থেকে এটি ফিরিয়ে আনা, বেনামে ফাংশনটির মধ্যে কলব্যাক ইত্যাদি

উত্তর:


613

আপনার sleepফাংশনটি কাজ করে না কারণ setTimeout(এখনও?) এমন কোনও প্রতিশ্রুতি দেয় যা awaitসম্পাদিত হতে পারে return আপনাকে এটি ম্যানুয়ালি প্রচার করতে হবে:

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function sleep(fn, ...args) {
    await timeout(3000);
    return fn(...args);
}

বিটিডব্লিউ, আপনার লুপটি কমিয়ে দেওয়ার জন্য আপনি সম্ভবত কোনও sleepফাংশন ব্যবহার করতে চান না যা কলব্যাক নেয় এবং এটি এটিকে পিছনে দেয়। আমি বরং কিছু করার প্রস্তাব দিই

while (goOn) {
  // other code
  var [parents] = await Promise.all([
      listFiles(nextPageToken).then(requestParents),
      timeout(5000)
  ]);
  // other code
}

যা parentsকমপক্ষে 5 সেকেন্ডের গণনা করতে দেয় ।


11
Love Promise.allপদ্ধতির। এত সহজ এবং মার্জিত!
আনশুল কোকা

4
var [parents]প্রতিনিধিত্ব স্বরলিপি কি ? আমি এটি আগে দেখিনি এবং গুগল করা খুব কঠিন বিষয়
natedog

6
@ নাট ইউশার এটি অ্যারে
বার্গি

1
@ টিঙ্কারার " অপেক্ষা করার প্রয়োজন হলে সময়সীমা অ্যাসিঙ্ক হিসাবে ঘোষণা করা দরকার " - না। একটি ক্রিয়াকলাপে কেবল এমন প্রতিশ্রুতি ফেরানো দরকার যা প্রতীক্ষিত হতে পারে (বা আসলে, তারপরে যথেষ্ট)। এটি কীভাবে এটি সম্পাদন করে যা কার্যটি বাস্তবায়নের উপর নির্ভর করে, এটির কোনও দরকার নেই async function
বার্গি

2
@naisanza না, async/ awaitহয় উপর ভিত্তি করে প্রতিশ্রুতি। কেবলমাত্র এটির পরিবর্তে thenকলগুলি।
বার্গি

150

নোড .6..6 থেকে আপনি promisifyইউটিউস মডিউল থেকে ফাংশনগুলি একত্রিত করতে পারেন setTimeout()

node.js

const sleep = require('util').promisify(setTimeout)

জাভাস্ক্রিপ্ট

const sleep = m => new Promise(r => setTimeout(r, m))

ব্যবহার

(async () => {
    console.time("Slept for")
    await sleep(3000)
    console.timeEnd("Slept for")
})()

1
নোডজেজেএস await require('util').promisify(setTimeout)(3000)এও প্রয়োজন ছাড়াই অর্জন করা যায়:await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000)
শিল

5
আকর্ষণীয় @ এসএইচএল। আমি মনে করি এটি যদিও আমার সমাধানের চেয়ে কম পঠনযোগ্য। লোকেরা যদি মতানৈক্য হয় তবে আমি কি এটি সমাধানে যুক্ত করতে পারি?
হ্যারি

2
প্রয়োজনীয় সংস্করণটি সংস্করণটির চেয়ে স্পষ্টতই ভাল getOwnPropertySymbols... এটি যদি না ভাঙে ...!
ম্যাট ফ্লেচার

2
এই যে @ হ্যারি। মনে হচ্ছে আপনি নিজের উত্তরটিতে ফ্ল্যাওয়ারস্পেসের উত্তর থেকে একটি লাইন অন্তর্ভুক্ত করেছেন। আমি আপনার উদ্দেশ্যগুলি অনুমান করতে চাই না, তবে এটি তাদের পক্ষে সত্যিই ন্যায্য নয়। আপনি কি আপনার সম্পাদনা রোলব্যাক করতে পারেন? এই মুহুর্তে এটিকে কিছুটা চৌর্যবৃত্তির মতো দেখাচ্ছে ..
ফলিক্স গাগনন-গ্রেনিয়ার

2
উত্তর ঠিক নীচে থাকায় আমি ওয়ান-লাইনার সরিয়ে ফেলেছি, তবে আমি অনেক জনপ্রিয় উত্তর দেখেছি তাদের উত্তরগুলি নতুন নতুন উত্তর অন্তর্ভুক্ত করার জন্য আপডেট করতে দেখেছি কারণ বেশিরভাগ পাঠক প্রথম কয়েকটি প্রতিক্রিয়াগুলির অতীত অনুসন্ধান করতে বিরক্ত করেন না।
হ্যারি

129

দ্রুত ওয়ানলাইনার, ইনলাইন উপায়

 await new Promise(resolve => setTimeout(resolve, 1000));

3
let sleep = ms => new Promise( r => setTimeout(r, ms));// একটি ওয়ান লাইনের ফাংশন
সলডেপ্লাটা সাকেটোস

8
এমনকি আরও খাটো :-)await new Promise(resolve => setTimeout(resolve, 5000))
লিরান ব্রিমার

1
আপনি যখন একই লাইনে 2 বার "সমাধান" x ব্যবহার করেন তখন এর অর্থ কী? পছন্দ: নতুন প্রতিশ্রুতির জন্য অপেক্ষা করুন (সমাধান => সেটটাইমআউট (সমাধান, 1000)); এটা রেফ না। নিজেই বা কি? পরিবর্তে আমি এর মতো কিছু করব: ফাংশন myFunc () {}; নতুন প্রতিশ্রুতির জন্য অপেক্ষা করুন (সমাধান => সেটটাইমআউট (মাইফঙ্ক, 1000));
পাবলডকে

35

setTimeoutকোনও asyncফাংশন নয়, সুতরাং আপনি এটি ES7 async-প্রতীক্ষার সাথে ব্যবহার করতে পারবেন না। তবে আপনি sleepES6 প্রতিশ্রুতি ব্যবহার করে আপনার ফাংশন বাস্তবায়ন করতে পারেন :

function sleep (fn, par) {
  return new Promise((resolve) => {
    // wait 3s before calling fn(par)
    setTimeout(() => resolve(fn(par)), 3000)
  })
}

তারপরে আপনি sleepES7 async- অপেক্ষার সাথে এই নতুন ফাংশনটি ব্যবহার করতে সক্ষম হবেন :

var fileList = await sleep(listFiles, nextPageToken)

দয়া করে মনে রাখবেন যে আমি কেবল আপনার ES7 async / সংযুক্তি সম্পর্কে আপনার প্রশ্নের উত্তর দিচ্ছি setTimeout, যদিও এটি প্রতি সেকেন্ডে খুব বেশি অনুরোধ প্রেরণে আপনার সমস্যার সমাধান করতে পারে না।


আপডেট করুন: আধুনিক Node.js সংস্করণ একটি buid-ইন ASYNC সময়সীমার প্রয়োগ, মাধ্যমে অ্যাক্সেসযোগ্য হয়েছে util.promisify সাহায্যকারী:

const {promisify} = require('util');
const setTimeoutAsync = promisify(setTimeout);

2
আপনার এটি করা উচিত নয়, যখন fnত্রুটি ছুঁড়ে ফেলা হয় না।
বার্গি

@ বার্গি আমার ধারণা new Promiseআপনি sleep.catchএটি করতে পারেন এমন জায়গায় এটি বুদবুদ হয়ে গেছে ।
ফ্লোরিয়ান ওয়েনডেলবোন

3
@ডোডেরাক্ট না, এটি একটি অ্যাসিনক্রোনাস setTimeoutকলব্যাকের মধ্যে রয়েছে এবং new Promiseকলব্যাক দীর্ঘকাল ধরে করা হয়েছে। এটি বৈশ্বিক প্রেক্ষাপটে বুদবুদ হবে এবং একটি অপরিবর্তিত ব্যতিক্রম হিসাবে নিক্ষিপ্ত হবে।
বার্গি

> প্রতি সেকেন্ডে অনেক বেশি অনুরোধ প্রেরণে সমস্যা। আপনি "ডাবনোইন" ব্যবহার করতে চান সম্ভবত ইউআই অনেক বেশি রুউকেস্ট গুলি চালানোর মতো জিনিসগুলিকে আটকাতে পারে।
ফ্লেভারস্কেপ

5

আপনি যদি একইরকম সিনট্যাক্স ব্যবহার করতে চান তবে আপনি যেমন setTimeoutকোনও সহায়ক ফাংশন লিখতে পারেন:

const setAsyncTimeout = (cb, timeout = 0) => new Promise(resolve => {
    setTimeout(() => {
        cb();
        resolve();
    }, timeout);
});

এরপরে আপনি এটিকে এভাবে কল করতে পারেন:

const doStuffAsync = async () => {
    await setAsyncTimeout(() => {
        // Do stuff
    }, 1000);

    await setAsyncTimeout(() => {
        // Do more stuff
    }, 500);

    await setAsyncTimeout(() => {
        // Do even more stuff
    }, 2000);
};

doStuffAsync();

আমি একটি বক্তব্য করেছি: https://gist.github.com/DaveBitter/f44889a2a52ad16b6a5129c39444bb57


1
মত একটি ফাংশন নাম delayRunএখানে আরও অর্থবোধ করতে পারে, যেহেতু এটি এক্স সেকেন্ডের মধ্যে কলব্যাক ফাংশনটি চলতে বিলম্ব করবে। খুব প্রতীক্ষিত উদাহরণ নয়, আইএমও।
মিশ্রিত 3 ই

2
var testAwait = function () {
    var promise = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Inside test await');
        }, 1000);
    });
    return promise;
}

var asyncFunction = async function() {
    await testAwait().then((data) => {
        console.log(data);
    })
    return 'hello asyncFunction';
}

asyncFunction().then((data) => {
    console.log(data);
});

//Inside test await
//hello asyncFunction

0

নিম্নলিখিত কোডটি ক্রোম এবং ফায়ারফক্স এবং সম্ভবত অন্যান্য ব্রাউজারগুলিতে কাজ করে।

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function sleep(fn, ...args) {
    await timeout(3000);
    return fn(...args);
}

তবে ইন্টারনেট এক্সপ্লোরারে আমি এর জন্য একটি সিনট্যাক্স ত্রুটি পাই "(resolve **=>** setTimeout..."


0

ডেভ এর উত্তর থেকে অনুপ্রাণিত একটি ব্যবহার করেছেন

doneঅপারেশন শেষ হয়ে গেলে কল করার জন্য কলব্যাকের মধ্যে মূলত পাস ।

// Function to timeout if a request is taking too long
const setAsyncTimeout = (cb, timeout = 0) => new Promise((resolve, reject) => {
  cb(resolve);
  setTimeout(() => reject('Request is taking too long to response'), timeout);
});

আমি এটি এইভাবে ব্যবহার করি:

try {
  await setAsyncTimeout(async done => {
    const requestOne = await someService.post(configs);
    const requestTwo = await someService.get(configs);
    const requestThree = await someService.post(configs);
    done();
  }, 5000); // 5 seconds max for this set of operations
}
catch (err) {
  console.error('[Timeout] Unable to complete the operation.', err);
}


-3

এটি ওয়ান-লাইনারে দ্রুত সমাধান।

আশা করি এটি সাহায্য করবে।

// WAIT FOR 200 MILISECONDS TO GET DATA //
await setTimeout(()=>{}, 200);

1
কাজ করে না। এই: await setTimeout(()=>{console.log('first')}, 200); console.log ('second')কপি করে প্রিন্ট দ্বিতীয় তারপর প্রথম
gregn3

1
@ গ্রেগন 3 হ'ল পয়েন্ট। এটি একটি নন-ব্লকিং সমাধান যেখানে মূল প্রোগ্রাম প্রবাহের বাইরে "ব্লকিং অপারেশন" সম্পন্ন হওয়ার পরে ফাংশনের বাইরের কোডটি কার্যকর করা চালিয়ে যেতে পারে। যদিও আপনি এবং রমি এবং মোহামাদ যে সিনট্যাক্সটি সরবরাহ করেছেন তা অ্যাসিঙ্ক ফাংশনে (সম্ভবত সাম্প্রতিকতম সংযোজন হতে পারে) অপেক্ষার জন্য প্রয়োজনীয়তার কারণে কঠোরভাবে সঠিক নয়, এছাড়াও আমি নোড.জেএস ব্যবহার করছি। এটি আমার টুইটযুক্ত সমাধান। var test = async () => { await setTimeout(()=>{console.log('first')}, 1000); console.log ('second') }এর কার্যকারিতাটি দেখানোর জন্য আমি সময়সীমা বাড়িয়েছি।
আজরিয়া
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.