Как работают обещания и обещания цепочки?[Проблема с кодом] - PullRequest
7 голосов
/ 08 апреля 2019

Я изучаю Node.js и пытаюсь правильно использовать модуль mysql2. Из-за этого я недавно начал изучать обещания.

Я пишу что-то вроде "библиотеки", поэтому я могу практиковать все эти темы, и, делая это, я столкнулся с проблемой цепочки обещаний, которую я не могу понять. Любая помощь приветствуется!

Проблема заключается в следующем:

Допустим, у меня есть функция query, которая выбирает базу данных, обрабатывает данные и возвращает обещание, поэтому я могу получить эти данные и работать с ними в каком-то другом файле.

Теперь, если я напишу свою query функцию следующим образом:


query(){
        let p = new Promise((resolve, reject) => {
            resolve("Hello world")
        });


        p.then(data => {
            console.log("Hello world a second time!");
        }).then(data => {
            console.log("Hello world a third time")
        })
        return p;
    }

и я пытаюсь «потреблять» это обещание из другого файла, например:


DBObject.query().then((data) => {
    console.log("Hello world from the other file!");
})

Тогда вывод в неправильном порядке, программа печатает это:

Hello world a second time!
Hello world from the other file!
Hello world a third time


С другой стороны, если я изменяю код в первом файле и не пытаюсь разделить цепочку обещаний, как это:

query(){
        let p = new Promise((resolve, reject) => {
            resolve("Hello world")
        }).then(data => {
            console.log("Hello world a second time!");
        }).then(data => {
            console.log("Hello world a third time")
        })

        return p;
    }

Отлично работает и печатает:

Hello world a second time!
Hello world a third time
Hello world from the other file!

Я не понимаю этого поведения, я думал, что объявление then блоков отдельно от определения обещания будет то же самое, что и цепочка обещаний, когда я объявляю обещание, и это явно не так!

Заранее спасибо за ответы, которые вы можете дать мне. Кроме того, было бы здорово, если бы вы могли дать мне несколько советов о том, как правильно писать такой код. Я имею в виду, если я напишу код, который использует обещания, что я должен вернуть пользователю? Еще одно обещание? Или просто данные для работы? Мне бы очень хотелось написать код, который будет следовать «стандартному» образу действий.

Приветствую вас всех! Еще раз спасибо.

Ответы [ 2 ]

6 голосов
/ 08 апреля 2019

Если у вас есть одно Обещание, вы можете связать любое число Обещаний на его .then. Например

const p = Promise.resolve();
p.then(() => console.log('then 1');
p.then(() => console.log('then 2');

означает, что p имеет два Обещает, что ветвь от него при разрешении: 1 и 2 (в дополнение к самому обещанию p).

  p
 / \
/   \
1   2

Что вы делаете в своем первом коде

let p = new Promise((resolve, reject) => {
  resolve("Hello world")
});
p.then(data => {
  console.log("second");
}).then(data => {
  console.log("third")
})
return p;

похоже на

"Hello world" = <Promise you return>
    |
    |
    |
  second
    |
    |
    |
  third = <unused Promise expression that the then chain resolves to>

У вас есть две ветви: возвращаемое Обещание разрешается при выполнении Hello world, а не при third.

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

let p = new Promise((resolve, reject) => {
  resolve("Hello world")
}).then(data => {
  console.log("Hello world a second time!");
}).then(data => {
  console.log("Hello world a third time")
})

return p;

похоже на

"Hello world"
     |
     |
'Hello second'
     |
     |
'Hello third' = <Promise you return>

, где возвращенное Обещание - это то, которое разрешается сразу после выполнения Hello third.

4 голосов
/ 08 апреля 2019

Вместо возврата p в изолированной версии ... вернуть цепочку p.then(). Последний будет добавлен в конец этой цепочки, вместо того, чтобы создавать две разные цепочки

then() возвращает новое обещание, разрешенное любым возвратом, или undefined, если нет возврата

const query = () => {
  let p = new Promise((resolve, reject) => {
    resolve("Hello world")
  });

  return p.then(data => {
    // from `resolve()`
    console.log('Then 1: ', data)
    // return to next then()
    return ("Hello world a second time!");
  }).then(data => {
    // from previous then()
    console.log('Then 2: ', data)
    // return to next then()
    return ("Hello world a third time")
  });
}


query().then(res => console.log('Final: ', res))
...