在异步函数中返回Promise

时间:2017-04-21 14:49:40

标签: javascript node.js asynchronous promise

简而言之,我的问题是:

  1. 如果使用蓝鸟本来应该是" promisifying"东西?
  2. 在这些情况下我应该只用callan显式承诺。(解决|拒绝) 在子异步函数中,并附加一个返回值,就像第二个函数的格式一样?
  3. 我可能错误地理解了promises的控制流,当fs.readFile中的所有东西都很好时,它们应该按照它们应该去的那样,是异步代码在遇到拒绝时不能模拟返回吗?
  4. Promise被拒绝后运行的异步函数会发生什么?它只是将结果返回给等待Promise的那个,然后异步代码就会一直闲逛,做任何想做的事情直到完成吗?

    • 它基本上只是将整个事物视为一个大型发电机,没有产量告诉它此时停止执行吗?
  5. 我有最后一个问题,但是搜索它可能会回答它。我的承诺链方法是否正确?我以前曾经使用过它们,偶尔也会遇到未处理的拒绝问题。我正在设置一个catch块,这样做有利于以格式.then((res)=> {...},(rej)=> {...})运行,因为它是一个antiPattern,如上所述由PromisesA +约定。

  6. 我最近遇到过关于使用Promise的问题,我有点理解所述行为背后的逻辑,但有些部分没有完全点击。

    问题是我有一些代码调用异步函数,为了使用fs.readFile将其与大多数Node用户联系起来。当执行下面的代码时,我会继续遇到Promise拒绝或进入它的拒绝条款的情况,但正在执行该函数的其余部分。

    由于返回强制执行本机控制流,我得到了第二次迭代工作的原因,但我也想到了函数调用的Promise包装器,因为它实现了它自己的流控制,一旦它#&# 39; s触发解析/拒绝功能,终止该功能。这似乎不是这种情况,因为函数会拒绝并进入它的解析语句。打破任何突然出现的东西。在其他子功能下可以看到相同的行为,即运行失败的请求和其他异步功能。我不确定它是否也会影响同步代码。

    注意

    下面的代码片段不会在NodeJs之外运行,我还不知道如何在JSFiddle中处理它,而且我认为所需的fs模块是特定于节点的。

    /*
     Seemingly bypassing my Promise's reject statements
     This does not only happen with fs, but with other none natively promise based sub
     libraries.
     Is it because I am not inherrently promisifying things, should I just return a Promise.resolve within the sub Asynchronous function, and attach a return to it, like the format for the 2nd function?
    
    I may be understanding the control flow of the promises incorrectly, when everything is good within the fs.readFile things will go as they should, since the last thing being done is basically resolving, and the control flow is implicitly acting like that native flow.
     */
    const Promise = require('bluebird'),
      fs = require('fs'),
      fName = './tmpFs.txt';
    
    const retPromExample = () => {
      return new Promise((resolve, reject) => {
        fs.readFile(fName, (err, fd) => {
          if (err) {
            // The if condition is applied and satisfied
            console.log("\nI got in here, and I know I've failed\n");
            reject(err)
          }
          // It still gets here, even though err is clearly not null, if the file does not exist
          console.log("I'm outside the if(err) with ", err);
          // Do something with the file, try and JSON.parse it, and fd is undefined.
          resolve("What I wanted to do was done. Resolving\n")
        })
      })
    };
    
    const retPromExample_deux = () => {
      // On the rejection getting an unhandled rejection error as well. Am I following the syntax for this correctly?
      return new Promise((res, rej) => {
        return fs.readFile(fName, (err, fd) => {
          if (err) {
            // The if condition is applied and satisfied
            return Promise.reject("Part Deux; I got in here, and I know I've failed %s \n", err)
          }
          // Under this case an explicit return is given, it should not reach here. If the file does not exist. Err should be null.
          console.log("I'm outside the if(err) with ", err);
          // Base control Flow states that this should not fail in any manner.
          return Promise.resolve("What I wanted to do was done. Resolving")
        })
      })
    };
    
    // Toggle which is run with node FSTest.js 1 or Nothing.
    if (process.argv.find(val => val === '1'))
      retPromExample()
      .then(val => console.log(val))
      .catch(err => console.log(err));
    else
      retPromExample_deux()
      .then(val => console.log(val))
      .catch(err => console.log(err));
    

1 个答案:

答案 0 :(得分:1)

前言:您的retPromExample大部分是正确的。 retPromExample_deux不是。 :-)详情如下。

  

1。如果使用蓝鸟应该固有地“宣传”​​东西?

没有。只有实际使用它们才会使用它们。

  

2。在这些情况下,我应该只是在子异步函数中调用显式Promise。(resolve | reject),并附加一个返回值,就像第二个函数的格式一样?

不(更晚些时候)。

  

3。我可能错误地理解了promises的控制流,当fs.readFile内的所有内容都很好时,异步代码在遇到reject时不会模拟返回吗?

如果一切顺利,您不应该到达reject(更多信息如下)。

它没有模拟回报,而是解决了你已经回归的承诺。

  

4。承诺被拒绝后,正在运行的异步函数会发生什么?

在您的情况下,在解析/拒绝承诺(统称为“已解决”)时,启动异步过程(readFile)的函数早已结束,并且底层异步I / O进程也在那时完成,因为你是从完成回调中完成的。

  

5。 ......我的承诺链方法是否正确?我之前使用过它们,偶尔会遇到未处理的拒绝问题。我正在设置一个catch块,这样做有利于以格式.then((res)=> {...},(rej)=> {...})运行,因为它是一个antiPattern,如上所述通过PromisesA +惯例。

问题末尾的承诺链很好。我不知道使用then的第二个参数是任何类型的反模式,但我个人更喜欢使用catch,因为格式化原因与其他任何内容一样。

你不会从你所展示的链中得到“未处理的拒绝”错误,因为你总是处理拒绝。您retPromExample_deux收到“未处理的拒绝”错误,因为您使用Promise.resolvePromise.reject创建的承诺永远不会被消费,这意味着拒绝{ {1}}无法处理。 (这是Promise.reject不正确的原因之一。)

重新启动retPromExample_deux:这几乎就是你如何使用非承诺异步回调API(如retPromExample)使用承诺,除非你想要一个你遗失的readFile:< / p>

else

如果出现错误并且您const retPromExample = () => { return new Promise((resolve, reject) => { fs.readFile(fName, (err, fd) => { if (err) { console.log("\nI got in here, and I know I've failed %s\n", err); reject(err) } else { // <==== *** Here *** console.log("I'm outside the if(err) with ", err); resolve("What I wanted to do was done. Resolving\n") } }) }) }; 承诺,那么您就不希望继续使用您的成功逻辑并致电reject(尽管在已确定的承诺上呼叫resolve是无操作的。

您的resolve不正确,因为它是来自promise执行者(您传递给retPromExample_deux的函数)和new Promise回调的返回值。根本readFile构造函数和Promise都不会使用这些返回值。你回来的承诺永远不会得到解决。