мы можем использовать async / await для функций класса в javascript? [Дубликат]

То, что вы видите здесь, на самом деле является эффектом двух закруглений. Числа в ECMAScript представляют собой внутренне представленную точку с плавающей запятой с двойной точностью. Если для параметра id установлено значение 714341252076979033 (0x9e9d9958274c359 в шестнадцатеричном формате), ему фактически присваивается ближайшее представимое значение двойной точности, которое равно 714341252076979072 (0x9e9d9958274c380). Когда вы распечатываете значение, оно округляется до 15 значащих десятичных цифр, что дает 14341252076979100.

49
задан Felix Kling 26 February 2016 в 19:08
поделиться

3 ответа

Возвращаемое значение всегда будет обещанием. Если вы явно не вернете обещание, возвращаемое вами значение автоматически будет завернуто в обещание.

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));

В моем резюме поведение действительно противоречит традиционным операторам return. Похоже, что когда вы явно возвращаете значение non-prom из функции async, оно принудительно завершает его в обещание. У меня нет большой проблемы с этим, но он бросает вызов нормальному JS.

ES6 имеет функции, которые не возвращают точно то же значение, что и return. Эти функции называются генераторами.

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

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

// Logs 'test'.
console.log(foo().next().value);
56
ответ дан Nathan Wall 20 August 2018 в 06:46
поделиться
  • 1
    «возвращаемое вами значение автоматически будет завернуто в обещание». статическим методом Promise.resolve, т. е. если оператор возврата async-функции - return x; он неявно становится - возвращает Promise.resolve (x); – adnan2nd 12 November 2017 в 19:01

async не возвращает обещание, ключевое слово await ожидает разрешения обещания. async - это расширенная функция генератора, и ожидание работает немного подобно yield

Я думаю, что синтаксис (я не уверен на 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 является довольно типичным генератором на основе Promise

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);
    });
  });
}
-2
ответ дан akc42 20 August 2018 в 06:46
поделиться
  • 1
    " async является улучшенной функцией генератора ". - Нет, это действительно так. – Bergi 10 February 2016 в 12:52
  • 2
    Как указано выше - «асинхронные функции» действительно возвращают обещание. Концептуально, по крайней мере, основной точкой выражения async является перенос возвращаемых значений функции в обещание. Вы можете даже «ждать» на простой старой функции, которая возвращает Promise, и все это работает, потому что функция async '===' возвращает Promise. – spechter 8 May 2018 в 07:43
  • 3
    @bergi, на самом деле, это расширенная функция генератора. функция генератора, которая всегда возвращает обещание .. или что-то в этом роде. – Alexander Mills 18 August 2018 в 08:31

Я просмотрел спецификацию и нашел следующую информацию. Краткая версия - это async function desugars к генератору, который дает Promise s. Итак, да, асинхронные функции возвращают обещания.

Согласно tc39 spec , верно следующее:

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

Desugars to:

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); });
    });
}
7
ответ дан Jon Surrell 20 August 2018 в 06:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: