【问题标题】:Wrap two promise in a function在一个函数中包装两个 Promise
【发布时间】:2017-09-08 14:30:12
【问题描述】:

我对承诺的回报有些问题。之前,在 http 调用期间,我使用了这样的函数,返回一个 promise:

get_data: function (url)
{
     let timestamp = new Date();
     return $http({
         method: "GET",
         url: url
         headers: {
              'timestamp': timestamp,
         }
     }).then(
            function successCallback(response)
            {

                console.dir("Response:");
                console.dir(response["data"]);

                return (response["data"])
            },
            function errorCallback(response)
            {
                console.dir(response);
                return response;
            });
    },

这很简单,我可以这样使用它:

get_data('my_awesome_url').then(function(response){
    let my_awesome_data = response
})

罪魁祸首是时间戳。我将它用于一些身份验证,原因并不重要,但通过从客户端获取它,我经常成为另一种语言的坏钟表或系统本地设置的受害者。

我的解决方案是创建一个请求服务器时间戳的函数。但是通过这样做,我必须首先等待时间戳请求,然后启动另一个请求并......等待它结束。 这是我真的不知道该怎么做的地方。我的代码如下所示:

get_data: function (url)
{
     let timestamp = new Date();
     get_timestamp().then(function(){
         return $http({
             method: "GET",
             url: url
             headers: {
                  'timestamp': timestamp,
             }
         }).then(
                function successCallback(response)
                {

                    console.dir("Response:");
                    console.dir(response["data"]);

                    return (response["data"])
                },
                function errorCallback(response)
                {
                    console.dir(response);
                    return response;
                });
        });
    },

但我不确定我应该返回什么。我应该返回 get_timestamp 承诺并在“then”中等待另一个请求结束吗?我应该让 get_timestamp 成为一个同步调用,因为毕竟它只是一个小日期字符串吗? 我在我的代码中一直使用旧函数,所以一种只保留旧用法(当时只有一个)的方法会很棒。

一如既往地感谢大家。

【问题讨论】:

  • return get_timestamp().then(function(){...

标签: javascript angularjs asynchronous promise angular-http


【解决方案1】:

你会这样写:

get_data: function(url) {
  return get_timestamp() // request the timestamp this returns a promise
    .then(function(timestamp) {   // on which then is called wich itself returns a promise.
                         // the callback of this then is called as soon 
                         // as the promise returned by timestamp
                         // is resolved
      return $http({
        method: "GET",
        url: url
        headers: {
          'timestamp': timestamp,
        }
      }) // here you return the Promise that is created by the $http
    })
    .then(function(response) { // the callback of this then is called as soon
                               // as the previous promise was resolved

      console.dir("Response:");
      console.dir(response["data"]);

      return (response["data"])
    })
    .catch(function(response) {
      console.dir(response);
      return response;
    });
},

首先我会使用:

.then(function(response) {
  console.dir("Response:");
  console.dir(response["data"]);

  return (response["data"])
})
.catch(function(response) {
  console.dir(response);
  return response;
});

代替

.then(
  function successCallback(response) {

    console.dir("Response:");
    console.dir(response["data"]);

    return (response["data"])
  },
  function errorCallback(response) {
    console.dir(response);
    return response;
  });
})

因为如果你有更长的链,以后更容易阅读。

return 返回通过链创建的最后一个 Promise,即调用 .catch(function(response) {...} 返回的 Promise

【讨论】:

  • @t-niese 命名函数对每个人来说都是一件好事,如果抛出错误,可以更容易地理解调用堆栈。如果 OP 可以使用稍微冗长的代码,你不应该阻止它。
  • @skylize 与其说是命名函数,不如说是.then(success, error).then(callback).catch(callback)。使用.catch 可以更轻松地在以后找到那些.catch 语句。使用.then(success, error) 时,这些错误回调并不容易看到/找到。 OP 会捕获错误,因此它不会出现在任何错误堆栈中,因此在这种特殊情况下,命名函数不太可能有好处。
  • 只是为了确保,除了明显的语法,.catch 和 .then(success, error) 的工作方式相同?
  • @t-niese 啊,好的。我个人觉得在许多情况下使用.then(success, error) 有助于直观地阐明哪些承诺有可能被抛出。我会使用 `.catch(error) 作为后备。但这似乎主要是风格,并不会真正影响最终结果。
  • @skylize @RaphaelTodo 哦,在这种特殊情况下,我的想法是错误的,我会相应地更新我的答案。我忘记了角度不会将错误传递给拒绝。在这种情况下,then 是比 catch 更好的解决方案,并且必须直接与回调中的 $http 一起放置。
【解决方案2】:

你应该链接 Promises 并返回链接的结果:

function get_data(url) {
  return get_timestamp()
    .then((timestamp) => {
      return $http({
         method: "GET",
         url: url,
         headers: {
           timestamp: timestamp
         }
      });
    })
    .then((response) => {
      console.dir("Response:");
      console.dir(response["data"]);

      return response["data"];
    })
    .catch((response) => {
      console.dir(response);
      return response;
    });
}

请注意,我们只需要在链的末尾有一个.catch 即可捕获所有异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 2018-05-17
    相关资源
    最近更新 更多