async / प्रतीक्षारत अनुमानित रूप से रिटर्न का वादा?


111

मैंने पढ़ा कि asyncकीवर्ड द्वारा चिह्नित async फ़ंक्शंस एक वादा वापस करते हैं:

async function getVal(){
 return await doSomethingAync();
}

var ret = getVal();
console.log(ret);

लेकिन वह सुसंगत नहीं है ... doSomethingAsync()एक प्रतिज्ञा मानकर , और प्रतीक्षित कीवर्ड वादा से मूल्य लौटाएगा, न कि वादा itsef, तो मेरे getVal फ़ंक्शन को उस मूल्य को वापस करना चाहिए , न कि एक अंतर्निहित वादा।

तो वास्तव में मामला क्या है? क्या एसिंक्स कीवर्ड द्वारा चिह्नित कार्य निहित रूप से वापसी के वादे हैं या क्या हम नियंत्रित करते हैं कि वे क्या लौटाते हैं?

शायद अगर हम स्पष्ट रूप से कुछ वापस नहीं करते हैं, तो वे स्पष्ट रूप से एक वादा वापस करते हैं ...?

अधिक स्पष्ट होने के लिए, उपरोक्त और के बीच अंतर है

function doSomethingAync(charlie) {
    return new Promise(function (resolve) {
        setTimeout(function () {
            resolve(charlie || 'yikes');
        }, 100);
    })
}

async function getVal(){
   var val = await doSomethingAync();  // val is not a promise
   console.log(val); // logs 'yikes' or whatever
   return val;  // but this returns a promise
}

var ret = getVal();
console.log(ret);  //logs a promise

मेरे सारांश में व्यवहार वास्तव में पारंपरिक रिटर्न स्टेटमेंट के साथ असंगत है। ऐसा प्रतीत होता है कि जब आप किसी asyncफ़ंक्शन से स्पष्ट रूप से एक गैर-वादा मूल्य वापस करते हैं, तो यह उसे एक वादा में लपेट देगा। मैं इसके साथ एक बड़ी समस्या नहीं है, लेकिन यह सामान्य जेएस की अवहेलना करता है।


1
क्या console.logदिखाता है?
बरमार

यह वादा संकल्प समारोह द्वारा पारित मूल्य है, वादा ही नहीं
अलेक्जेंडर मिल्स

शायद प्रतिज्ञा से परिणाम का इंतजार है।
हेमलेट हकोबयन 21

वास्तव में, मैं गलत था, यह एक वादा करता है
अलेक्जेंडर मिल्स

2
जावास्क्रिप्ट के वादे c # async प्रतीक्षित व्यवहार की नकल करने की कोशिश कर रहे हैं। हालाँकि, ऐतिहासिक रूप से उस जगह का समर्थन करने के लिए बहुत सी संरचना थी, जिसमें c # और जावास्क्रिप्ट में कोई भी नहीं था। इसलिए कई उपयोग मामलों में यह बहुत समान प्रतीत हो सकता है, यह कुछ हद तक एक मिथ्या नाम है।
ट्रैविस जे

जवाबों:


138

वापसी मूल्य हमेशा एक वादा होगा। यदि आप स्पष्ट रूप से एक वादा वापस नहीं करते हैं, तो आपके द्वारा लौटाया गया मूल्य स्वचालित रूप से एक वादे में लिपट जाएगा।

async function increment(num) {
  return num + 1;
}

// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));

एक ही बात है, भले ही वहाँ एक है await

function defer(callback) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(callback());
    }, 1000);
  });
}

async function incrementTwice(num) {
  const numPlus1 = await defer(() => num + 1);
  return numPlus1 + 1;
}

// Logs: 5
incrementTwice(3).then(num => console.log(num));

ऑटो-अनप्रॉप का वादा करता है, इसलिए यदि आप एक asyncफ़ंक्शन के भीतर से एक मूल्य के लिए एक वादा वापस करते हैं, तो आपको मूल्य के लिए एक वादा मिलेगा (मूल्य के लिए एक वादा के लिए वादा नहीं)।

function defer(callback) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(callback());
    }, 1000);
  });
}

async function increment(num) {
  // It doesn't matter whether you put an `await` here.
  return defer(() => num + 1);
}

// Logs: 4
increment(3).then(num => console.log(num));

मेरे सारांश में व्यवहार वास्तव में पारंपरिक रिटर्न स्टेटमेंट के साथ असंगत है। ऐसा प्रतीत होता है कि जब आप स्पष्ट रूप से एक async फ़ंक्शन से एक गैर-वादा मूल्य वापस करते हैं, तो यह एक वादे में लपेट देगा। मैं इसके साथ एक बड़ी समस्या नहीं है, लेकिन यह सामान्य जेएस की अवहेलना करता है।

ES6 में फ़ंक्शन होते हैं जो बिल्कुल उसी मान के रूप में वापस नहीं आते हैं return। इन कार्यों को जनरेटर कहा जाता है।

function* foo() {
  return 'test';
}

// Logs an object.
console.log(foo());

// Logs 'test'.
console.log(foo().next().value);

3
"आपके द्वारा लौटाया जाने वाला मान स्वचालित रूप से एक वादे में लिपट जाएगा" स्थिर विधि Promise.resolve, यानी, यदि एक async फ़ंक्शन का रिटर्न स्टेटमेंट है - वापसी x; यह स्पष्ट रूप से हो जाता है - वापसी Promise.resolve (x);
adnan2nd

क्या इसे स्पष्ट रूप से स्वयं बनाने के बजाय स्वचालित रूप से बनाए गए वादे को वापस करने के लिए बुरा व्यवहार माना जाता है? किसी तरह मैं कई मामलों में स्वच्छ दृष्टिकोण पसंद करता हूं।
marlar

24

मैंने कल्पना पर एक नज़र डाली और निम्नलिखित जानकारी प्राप्त की। लघु संस्करण यह है कि async functionएक जनरेटर के लिए एक desugars जो पैदावार Promiseएस। तो, हाँ, async कार्य वादे वापस करते हैं

Tc39 युक्ति के अनुसार , निम्नलिखित सत्य है:

async function <name>?<argumentlist><body>

Desugars:

function <name>?<argumentlist>{ return spawn(function*() <body>, this); }

जहां spawn"निम्नलिखित एल्गोरिथ्म के लिए एक कॉल है":

function spawn(genF, self) {
    return new Promise(function(resolve, reject) {
        var gen = genF.call(self);
        function step(nextF) {
            var next;
            try {
                next = nextF();
            } catch(e) {
                // finished with failure, reject the promise
                reject(e);
                return;
            }
            if(next.done) {
                // finished with success, resolve the promise
                resolve(next.value);
                return;
            }
            // not finished, chain off the yielded promise and `step` again
            Promise.resolve(next.value).then(function(v) {
                step(function() { return gen.next(v); });
            }, function(e) {
                step(function() { return gen.throw(e); });
            });
        }
        step(function() { return gen.next(undefined); });
    });
}

"संक्षिप्त संस्करण यह है कि एक async फ़ंक्शन जनरेटर को देता है जो वादा करता है कि पैदावार देता है।" मैं तुम्हें भ्रमित किया जा सकता है लगता है async functionके साथ async function*। पूर्व बस एक वादा वापस करता है। उत्तरार्द्ध एक जनरेटर देता है जो पैदावार का वादा करता है।
cdhowie

यह उत्तर काफी हद तक कल्पना का संदर्भ है और समीक्षा के बाद, मुझे विश्वास नहीं होता कि कोई भ्रम है। यह सच है, async फ़ंक्शंस वादे वापस करते हैं, लेकिन ऐसा करने के लिए वे उन जनरेटर के लिए उतरते हैं जो वादे करते हैं।
जॉन सरेल


-3

async वादा वापस नहीं करता है, प्रतीक्षित कीवर्ड वादा के संकल्प का इंतजार करता है। async एक बढ़ा हुआ जनरेटर फ़ंक्शन है और यह प्रतीक्षा पैदावार की तरह काम करता है

मुझे लगता है कि वाक्य रचना (मुझे 100% यकीन नहीं है) है

async function* getVal() {...}

ES2016 जनरेटर फ़ंक्शन इस तरह से थोड़ा काम करते हैं। मैंने थकाऊ के शीर्ष पर एक डेटाबेस हैंडलर बनाया है जो आप इस तरह से प्रोग्राम करते हैं

db.exec(function*(connection) {
  if (params.passwd1 === '') {
    let sql = 'UPDATE People SET UserName = @username WHERE ClinicianID = @clinicianid';
    let request = connection.request(sql);
    request.addParameter('username',db.TYPES.VarChar,params.username);
    request.addParameter('clinicianid',db.TYPES.Int,uid);
    yield connection.execSql();
  } else {
    if (!/^\S{4,}$/.test(params.passwd1)) {
      response.end(JSON.stringify(
        {status: false, passwd1: false,passwd2: true}
      ));
      return;
    }
    let request = connection.request('SetPassword');
    request.addParameter('userID',db.TYPES.Int,uid);
    request.addParameter('username',db.TYPES.NVarChar,params.username);
    request.addParameter('password',db.TYPES.VarChar,params.passwd1);
    yield connection.callProcedure();
  }
  response.end(JSON.stringify({status: true}));

}).catch(err => {
  logger('database',err.message);
  response.end(JSON.stringify({status: false,passwd1: false,passwd2: false}));
});

ध्यान दें कि मैं कैसे इसे विशेष रूप से सामान्य तुल्यकालिक की तरह प्रोग्राम करता हूं

yield connection.execSql और कम से yield connection.callProcedure

Db.exec फंक्शन काफी विशिष्ट प्रॉमिस बेस्ड जनरेटर है

exec(generator) {
  var self = this;
  var it;
  return new Promise((accept,reject) => {
    var myConnection;
    var onResult = lastPromiseResult => {
      var obj = it.next(lastPromiseResult);
      if (!obj.done) {
        obj.value.then(onResult,reject);
      } else {
       if (myConnection) {
          myConnection.release();
        }
        accept(obj.value);
      }
    };
    self._connection().then(connection => {
      myConnection = connection;
      it = generator(connection); //This passes it into the generator
      onResult();  //starts the generator
    }).catch(error => {
      reject(error);
    });
  });
}

4
" async एक बढ़ाया जनरेटर फ़ंक्शन है " - नहीं, यह वास्तव में नहीं है।
बरगी 11

जैसा कि ऊपर कहा गया है - 'async functions' वास्तव में एक प्रॉमिस लौटाते हैं। वैचारिक रूप से कम से कम, 'async' कथन का मुख्य बिंदु उस फ़ंक्शन के रिटर्न मानों को किसी वादे में लपेटना है। आप एक पुराने पुराने फ़ंक्शन पर 'प्रतीक्षा' भी कर सकते हैं जो एक वादा लौटाता है, और यह सब काम करता है, क्योंकि 'async function' === 'function' Promise लौट रहा है '।
18'18

2
@bergi, वास्तव में, यह एक बढ़ाया जनरेटर फ़ंक्शन है। एक जनरेटर फ़ंक्शन जो हमेशा एक वादा देता है .. या कुछ और।
अलेक्जेंडर मिल्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.