Обещания Нолана / головоломки JavaScript a+

я прочитала у нас проблема с обещаниями Нолан Лоусон несколько раз, но все еще есть некоторые вопросы об обещаниях в JavaScript. В конце поста Нолана вы можете найти ответы на четыре головоломки (я приложил скриншоты здесь).

так, у меня есть несколько вопросов:

  1. почему doSomethingElse() функция в 1-й головоломки есть undefined значение? По-моему, должно быть ... --2--> как в 4-м головоломка.

  2. в чем разница между 3-й и 4-й головоломки? В 3-й головоломки в первой then пишем doSomethingElse() и в 4-й головоломке мы пишем здесь только название функции,doSomethingElse. Как это возможно? Что действительно doSomethingElse сделать внутри then 4-й пазл?

  3. почему doSomethingElse() функция в 3-й головоломки начать в тот же момент, как doSomething?

Puzzle 1 and 2 Puzzle 3 and 4

6 ответов


  1. почему doSomethingElse() функция в 1-й головоломки [пройти]undefined?

давайте рассмотрим более простой пример:

foo();   // Line #1
foo(42); // Line #2

разница между двумя линиями в чем? В строке #1 мы вызываем foo, но не передаем его значение (следовательно undefined) в то время как на линии № 2 мы вызываем foo и передаем его 42.

возвращаясь к сообщению:

doSomething().then(function () {
    return doSomethingElse( );
    //                     ^-- we are not passing a value
}).then(finalHandler);

чем это отличается от 4-й пазл? В 4-я головоломка мы передаем ссылку на функцию в then. Предоставление обещания ссылка на функцию позволяет ей вызывать его в более позднее время с результатом обещания.[1]


  1. в чем разница между 3-й и 4-й головоломки? В 3-й головоломке [...] мы пишем doSomethingElse() и в 4-й головоломке мы пишем [...] doSomethingElse.

чтобы объяснить различия в 3-й и 4-я головоломка, давайте посмотрим на более простые примеры. Чем отличаются следующие две строки:

var foo = function foo() {
    return 42;
};
var a = foo;   // line #1
var b = foo(); // line #2

в фрагменте выше, a будет содержать ссылку на функцию foo, тогда как b будет содержать результат вызова foo (который будет 42).


  1. почему doSomethingElse() в 3-й головоломки начать в тот же момент, как doSomething?

похожие на различия между 3-м и 4-м функции, обратите внимание на использование () to invoke (или вызовов) функция. Здесь мы называем оба doSomething() и doSomethingElse() вместо того, чтобы ждать обещания "разрешить" (ожидание завершения первого вызова). прежде чем приступим к исполнению:

  1. выполнить doSomething который возвращает обещание
  2. прикрепите doSomethingElse() к обещанию-но подождите,doSomethingElse() - это нас зовет doSomethingElse(), Так что это произойдет асинхронно, и мы приложим обещание возвращение к обещанию doSomething() вернулся.
  3. прикрепить функцию finalHandler обещание

doSomething().then(function () {
  return doSomethingElse();
});

почему функция doSomethingElse () в 1-й головоломке имеет неопределенное значение? На мой взгляд, это должно привести к чему-то вроде 4-й головоломки.

обещанный результат doSomething передается анонимной функции (которая даже не принимает аргумент). Поэтому все, что там проходит, теряется. И doSomethingElse вызывается без каких-либо аргументов, поэтому первый аргумент функции undefined.

doSomething().then(doSomethingElse());

doSomething().then(doSomethingElse);

что разница между 3-й и 4-й уровень? В 3-й головоломке сначала пишем doSomethingElse (), а в 4-й головоломке пишем здесь только название функции - doSomethingElse. Как это возможно? Что на самом деле делает doSomethingElse в то 4-й головоломки?

функции в JavaScript-это объекты, которые вы можете передавать по своему усмотрению. Вот как на самом деле работает вся передача обратного вызова: есть функция (здесь это then), которая принимает функцию в качестве параметра, который затем позже вызывается.

таким образом, в последнем коде функция, которая передается в then is doSomethingElse Так что это функция, которая составляет позже называется. Но в первом случае мы называем doSomethingElse напрямую (в скобках ()). Так что передается then - это возвращаемое значение этой функции, которая вряд ли является функцией, которая может быть оценена после завершения обещания.

почему функция doSomethingElse () в 3-й головоломки начать в тот же момент, как doSomething?

как я уже сказал, функция немедленно вызывается, в то же время вы вызываете doSomething. Только возвращаемое значение передается в then который затем будет называться, как только обещание разрешится.


вы должны обратить внимание: doSomethingElse является ссылкой на функцию while doSomethingElse() означает, что вы сразу" вызываете " функцию. Здесь вы можете получить результат функции, если таковые имеются...

насчет обещаний я понял, что:

A) метод "then" принимает результат предыдущего вызова и передает его как параметр своему собственному параметру, если это функция.

B) выполнение задерживается только в том случае, если функция внутри метода " then что-то.

в этих ситуациях мы имеем:

головоломка 1) resultOfDoSomething используется в качестве параметра для анонимной функции

function (){ return doSomethingElse ();} 

Это doSomethingElse() без параметров.

головоломка 2) анонимная функция не возвращает данные, поэтому следующий "затем" немедленно выполняется

Головоломка 3) выражение doSomethingElse() является результатом вызова doSomethingElse. Это значение используется в качестве параметра для метода then, и поскольку он не является функцией (в данном примере!), мы можем перейти к другому "тогда"...

finalHandler получает последние допустимые результаты в качестве параметров, в этом случае resultOfDoSomething.

головоломка 4) Каждый метод "тогда" получает в качестве параметра ссылку на функцию. Каждая из этих функций будет вызываться с предыдущими результатами в качестве параметров. Таким образом, каждая функция должна ждать результата предыдущего выполнения... и вот у вас очередь из обещаний...


Long story short-простые 2 правила, чтобы сделать ваши примеры понятными:

  1. возврат значения изнутри .then Это то же самое, что вернуть обещание, которое разрешается с этим значением.

  2. когда вы ничего не возвращаете, это то же самое, что и возвращение undefined, который в свою очередь вводит правило #1.

Если вы держите эти 2 в виду, ваши обещания головоломки становятся ясными, как день.


почему doSomethingElse() функция в 1-й головоломки есть undefined значение? По-моему, должно быть ... --6--> как в 4-й головоломки.

Неа. The resultOfDoSomething передается обратному вызову, что then был вызван, да, но мы просто игнорируем его в первом коде:

doSomething().then(function(resultOfDoSomething) {
//               it's here: ^^^^^^^^^^^^^^^^^^^
    return doSomethingElse(  );
//          but not there: ^^ - Ooops!
});

в чем разница между 3-й и 4-й головоломки? В 3-й головоломке в первой тогда напишем doSomethingElse() и в 4-й головоломке мы пишем здесь только имя функции, doSomethingElse. Как это возможно? Что действительно doSomethingElse сделать внутри то 4-й головоломки?

как вы, вероятно, знаете, это разница между вызываемой функцией и самой функцией.

кроме того, мы всегда хотим - no: must - передать функцию обратного вызова в then(…). Следующие два эквивалентны:

promise.then(function callback(res) {
    …
});
function callback(res) {
    …
}
promise.then(callback);

это ожидается-вы передаете функцию вызову, поэтому она прикована к обещанию как обычный. Но!--13--> (с вызовом) больше не является функцией:

почему doSomethingElse() функция в 3-й головоломки начать в тот же момент, как doSomething?

потому что он вызывается сразу в выражении then(doSomethingElse()) - это на самом деле называется до then, к которому это аргумент. Так это на самом деле называется через мгновение после doSomething(), но на том же повороте цикла событий; и два асинхронных somethings будут работать в параллельный.

и then принимает только аргументы функции, все остальное -игнорировать. Таким образом, здесь нет цепей, это то же самое, что делать

var promise = doSomething();
doSomethingElse();
promise.then(finalHandler);

не то, что мы хотим!

кстати, они также объясняются как"Расширенная Ошибка #3: обещания против обещаний фабрики" и "Расширенная Ошибка #5: обещания проваливаются", которые я бы оба рассматривал как ошибки новичка : -)


Я думаю, что порядок выполнения всегда сначала doSomethingElse затем doSomethingElse и finalHandler. Это просто синтаксис JavaScript.

разница в том, что args передают функции разные.

две функции возвращают два обещания.Порядок выполнения двух обещаний показан на рисунках, которые вы разместили. Я думаю, что автор имеет в виду порядок двух обещаний, а не порядок выполнения функции.

/**
 * Created by tshungle on 17-2-24.
 */
'use strict'
function doSomething() {
  console.log("doSomething start");
  sleep(1000)
  console.log("doSomething end");
  return new Promise(function (resolve, reject) {
    setTimeout(function() {
      console.log("Promise of doSomething is about to resolve");
      resolve("doSomething resolvation")
    }, 2500);
  });

}

function doSomethingElse() {
  console.log("doSomethingElse start");
  sleep(1000);
  console.log("doSomethingElse end");
  return new Promise(function (resolve, reject) {
    setTimeout(function() {
      console.log("Promise of doSomethingElse is about to resolve");
      resolve("doSomethingElse resolvation")
    }, 2500);
  });
}

function finalHandler(result) {
  console.log("finalHandler result is:", result);
}

function sleep(ms) {
  var stop = new Date().getTime();
  while(new Date().getTime() < stop + ms) {
    ;
  }
}


//1
 doSomething().then(function () {
   return doSomethingElse();
 }).then(finalHandler);

//2
// doSomething().then(function () {
//   doSomethingElse();
// }).then(finalHandler);
//
//3
// doSomething().then(doSomethingElse())
//   .then(finalHandler);

//4
// doSomething().then(doSomethingElse)
//   .then(finalHandler);