【问题标题】:How to pass the final resolve variable in a promise chain with module exports?如何通过模块导出在承诺链中传递最终解析变量?
【发布时间】:2018-04-05 20:55:02
【问题描述】:

我在这里的最后一段代码上方有三个链式 promise:getChannel、getPlaylist 和 getVideoViews。

module.exports = {
 runScript: function(channelID, accessToken, callback) {
  YoutubeAPI.authenticate({
    type: "oauth",
    token: accessToken
  });


  getChannel(channelID)
  .then(getPlaylist)
  .then(getVideoViews)
  .then(function(views){
    callback(views);
  })
 }
}

我有另一个文件 user.js,它依赖于 getVideoViews 的解析(这是一个视频视图计数数组)。 user.js 中的代码如下:

      youtuber1.runScript(channelID, accessToken, function(error, response, views){
        console.log(views);
      });

但是,控制台日志会导致未定义。链接承诺让我很容易一个接一个地执行这些函数,但我现在很迷茫如何将最后一个函数的解析传递回我的 user.js。

我是一个有承诺和回调的初学者,希望得到一些帮助!

【问题讨论】:

  • 这与 Promise 或回调无关,它只是知道如何调用函数:p 你使用 callback(views); 调用回调 ... vs 回调 function(error, response, views) ....回调期望视图是第三个参数,您将其作为第一个参数传递 - 将 function(error, response, views){ 更改为 function(views){ 或 callback(views); 更改为 callback(null, null, views);
  • 您确定要混合使用 Promises 和 Callbacks 吗?您可以返回承诺链并在您的其他文件中调用then()。
  • aww 去@JaromandaX,谢谢!现在工作 100%。有时我希望我身边有像我这样的人在我做一些愚蠢的事情时告诉我,修复是一个 2 秒的修复,而不是花太多时间试图弄清楚一些愚蠢的事情!
  • 我第二个@Mark_M。您在这里将回调与承诺混合在一起。虽然它可能“有效”,但不一定是一种好习惯。

标签: javascript node.js callback promise google-cloud-functions


【解决方案1】:

只是为了补充Mark_M的答案,你也可以awaitpromises。

module.exports = {
    runScript: async function(channelID, accessToken) {
        YoutubeAPI.authenticate({
            type: "oauth",
            token: accessToken
        });
        var channel = await getChannel(channelID)
        var playlist = await getPlaylist(channel)
        var views = await getVideoViews(playlist)
        return views
    }
}

var views = await youtuber1.runScript(channelID, accessToken)

请注意,您只能等待异步函数中的内容。那是使用 async 关键字声明的函数。如果您不在任何功能范围内,可以使用IIFE

【讨论】:

    【解决方案2】:

    我在评论中提到了它,但它可能值得一个简短的例子,以防评论不清楚。

    既然你已经有了一个很好的承诺,你可以直接返回它而不用处理回调:

    module.exports = {
     runScript: function(channelID, accessToken, callback) {
      YoutubeAPI.authenticate({
        type: "oauth",
        token: accessToken
      });
      // return that promise
      return getChannel(channelID)
      .then(getPlaylist)
      .then(getVideoViews)
     }
    }
    

    然后在你的其他文件中,事情也变得更简单、更干净了:

    youtuber1.runScript(channelID, accessToken)
    .then(function(views){
       // your views are ready here
    })
    .catch(function(err){
       // deal with errors here
     }
    

    【讨论】:

    • 太棒了。我不知道这是可能的。这更有意义,也更干净。谢谢你,马克!
    • 我刚试过这个,当我运行它时,我得到了这个:TypeError:无法读取未定义的属性'then'。它指的是我的“其他文件”中的最后一个代码。看起来它正在尝试在 runScript 运行之前运行 .then(function(views)。我只是猜想是因为我将 console.log 放在您放置“您的视图已准备就绪”的位置,首先被调用然后导致错误。
    • 嗯,这表明 getChannel 没有返回任何内容。你确定runScript() 确实在工作并且getChannel 正在返回一些东西吗?
    • 我相信是的。因为当我更改回调以反映其他人提出的建议时,我可以在其他代码中控制台记录“视图”并返回正确的值。不过,这应该可行吗?我想让它工作!
    【解决方案3】:

    你的回调函数是function(error, response, views) { ... },但是当你在runScript中使用它时,你使用的是callback(views),所以参数不匹配。考虑用错误和响应参数做这样的事情(你可以做任何你需要的参数)。

    module.exports = {
     runScript: function(channelID, accessToken, callback) {
      YoutubeAPI.authenticate({
        type: "oauth",
        token: accessToken
      });
    
    
      getChannel(channelID)
      .then(getPlaylist)
      .then(getVideoViews)
      .then(function(views){
        callback(null, views);
      })
     }
    }
    

    user.js

    youtuber1.runScript(channelID, accessToken, function(error, response){
      console.log(response);
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 2020-01-15
      • 2014-07-01
      相关资源
      最近更新 更多