【问题标题】:Understanding Promise within Promise Javascript在 Promise Javascript 中理解 Promise
【发布时间】:2015-09-19 10:15:02
【问题描述】:

我已阅读:Promise - JavaScript | MDN 并在此处查看了本书中有关承诺的部分:Eloquent Javascript 以及其他谷歌搜索,但我似乎无法确定这是否是一个问题,因为我对 Promises 的理解或图书馆的混合物。我想要完成的是发出请求,检索响应,然后使用该响应发出另一个请求。我想我可以使用以下正常模式:

promiseObj.get('url')
.then(function(response){
    //do something with response
    var name = response.name;
    return name;
})
.then(function(name){
    //do something with name
}

但是有些东西不能正常工作。我正在尝试使用两个不同的 promise 对象来发出请求。我必须使用 podio API 发出请求,检索信息,然后使用 AngularJS $http 承诺。这是我的代码:

podio.request('get','/item/' + eventId).then(function(responseEvent) {
   ...   
   var imgId = responseEvent.img_id;
   ...
   return imgId;

}).then(function(imgId){
    console.log(imgId);

   var config = { responseType: 'arraybuffer'};
   $http.get('https://api.podio.com/file/' + imgId + '/raw',config)
   .then(function(response) {
        console.log('hi 2');
        var arr = new Uint8Array(response.data);
        var raw = String.fromCharCode.apply(null,arr);
        var b64 = btoa(raw);
        var dataURL = "data:image/jpeg;base64,"+b64;
        $scope.event.img.src = dataURL;
        },function(error){
           console.log(error);
        });
});

在我的第二个 then 中,我可以在控制台中看到 imgId,但之后没有任何反应。我可能会错过什么。

【问题讨论】:

  • imgId 不是承诺吗?
  • @MichaelPerrenoud 从传递给.then 的函数返回的任何值都被包装在一个Promise 中。

标签: javascript angularjs promise angular-promise


【解决方案1】:

如果您想创建两个 Promise,请尝试以下操作:

p1.get(function (response) {
  // Work with response here
  return response;
}).then(function (response) {
  return p2.get(response.urlMaybe);
}).then(function (response) {
  // Work on second response
});

大量伪善,但可能有一些帮助。

【讨论】:

  • 感谢您对如何返回下一个承诺然后调用它的简洁图片。这正是我需要的结构。在 google chrome 工具或 firefox 中是否有可以跟踪承诺的地方?
  • 我会使用调试器或一些console.logs。我认为我从未在开发工具中看到过这样的提及 Promises。找到东西就大声喊叫。
【解决方案2】:

一个原因可能是您没有外部承诺的错误处理程序,因此如果在您的console.log 之后引发异常,则可能无法检测到错误。我建议你扁平化你的 Promise 链,以便处理所有错误:

podio.request('get','/item/' + eventId)
  .then(function(responseEvent) {
    ...   
    var imgId = responseEvent.img_id;
    ...
    return imgId;
  })
  .then(function(imgId){
    console.log(imgId);
    var config = { responseType: 'arraybuffer'};
    return $http.get('https://api.podio.com/file/' + imgId + '/raw',config);
  })
  .then(function(response) {
    console.log('hi 2');
    var arr = new Uint8Array(response.data);
    var raw = String.fromCharCode.apply(null,arr);
    var b64 = btoa(raw);
    var dataURL = "data:image/jpeg;base64,"+b64;
    $scope.event.img.src = dataURL;
  },function(error){
     console.log(error);
  });

【讨论】:

  • 非常感谢您对拒绝功能的评论。我在变量名中发现了一个错误,导致我无法执行请求。非常感谢!
  • 当然这仍然不会在最后一个成功处理程序中捕获异常。
【解决方案3】:

除了 Adrian Lynch 的正确答案之外,假设我们还有一系列请求。每个请求都依赖于所有之前请求的结果。

promiseFn().then(function(resp) {
    return Promise.all([resp, otherPromiseFn(resp)]);
}).then(function(vals) {
    var first  = vals[0];
    var second = vals[1];
    return Promise.all([first, second, thirdPromiseFn(first, second)]);
});

..等等,聚合值。重要的是,每次你有一个 promise 返回函数调用时,你只需返回 promise,然后调用 then。请记住,您从传递给的函数返回的所有内容都会自动包装为您返回的值的承诺。

【讨论】:

  • 这是非常需要的建议。一旦我按照大家的建议让它工作,我的下一个问题是如何传递先前请求的结果。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-27
  • 1970-01-01
  • 2011-05-16
相关资源
最近更新 更多