Promise和Promise链如何工作? [代码问题]

时间:2019-04-08 01:58:18

标签: javascript node.js promise es6-promise

我正在学习Node.js,并尝试正确使用mysql2模块。因此,我最近开始研究诺言。

我正在写一种“库”,所以我可以练习所有这些主题,而在这样做的时候,我遇到了我无法真正理解的承诺链问题。任何帮助都将不胜感激!

问题如下:

比方说,我有一个query函数,该函数可获取数据库,处理数据并返回Promise,因此我可以获取该数据并在其他文件中使用它。

现在,如果我这样编写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


另一方面,如果我更改了第一个文件中的代码,并且我不尝试分开promise链,像这样:

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块与声明诺言时对诺言链接的权利是一回事,显然不是那样的!

预先感谢您可以给我的答案。另外,如果您能给我一些有关如何正确编写这样的代码的建议,那将是很棒的。我的意思是,如果我编写使用Promise的代码,应该返回给用户什么?另一个承诺?还是只是供他们使用的数据?我真的很想编写遵循“标准”做事方式的代码。

向大家致敬!再次谢谢你。

2 个答案:

答案 0 :(得分:6)

有了一个Promise时,您可以将任意数量的链式链接到其.then上。例如

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

表示p有两个 承诺在解析时从其分支:12(除了承诺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运行时,您返回的Promise会解决。

另一方面,当您在一个Promise上多次调用.then时,整个表达式将计算为Promise,当最后一个.then运行时,该Promise解析

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>

其中返回的Promise是运行Hello third之后立即解决的Promise。

答案 1 :(得分:4)

而不是在隔离版本中返回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))