【问题标题】:Promise.all and then (js)Promise.all 然后 (js)
【发布时间】:2017-06-28 17:03:17
【问题描述】:

我对整个承诺的事情有点陌生,所以我可能做错了什么。如果有人可以启发我,欢迎所有建议/信息。

所以这是我想要完成的代码(简化且绝对不是最佳的理解目的):

// Get data from webservice    
$scope.sendGet(id, option).then(function (response){
        // Fill the model
        $scope.model[option] = response.data;
    }).then(function(){
        if(option == $scope.PROFILES){

                var p1 = new Promise((resolve, reject) => {
                    $scope.getX1($scope.model[option][0][0].id);
                });
                var p2 = new Promise((resolve, reject) => {
                    $scope.getX2($scope.model[option][0][0].id);
                });
                var p3 = new Promise((resolve, reject) => {
                    $scope.getX3($scope.model[option][0][0].id);
                });
                var p4 = new Promise((resolve, reject) => {
                    $scope.my_data = JSON.parse($scope.model[option][0][0].list);
                });
            // Execute all promises to get the data
            Promise.all([p1,p2,p3,p4]).then(() => {
                debugger;
                // Do some validation and extra formatting on the data we just downloaded
                $scope.update();
            });
        }
    }).then(function(){
        // Display the data to the user
        $scope.move(option, 1, $scope.EDITING);
    });

这里的预期行为是:

获取数据 -> 使用此数据,使用 id 从 4 个来源(4 个承诺)获取数据 -> 下载所有数据后,更新一些引用并进行一些清理 -> 移动(这是一种更新的方法视图并做一些与 UI 相关的其他事情)

但由于某种原因,debugger;$scope.update(); 永远不会被执行。我尝试将这些移动到与 $scope.move() 函数相同的 .then 中,但它会在 Promise.all 中的数据被检索之前执行。

【问题讨论】:

  • 你的 p1-p4 承诺永远不会完成,因为你没有在其中任何一个中调用 resolve()reject()
  • 你永远不会解决你的承诺,因此他们永远不会执行 Promise.all 的“完成”回调。您的每个承诺 (p1-p4) 都应该有一个 resolve(value)reject(value)
  • 虽然,我应该指出,因为你使用的是 angularjs,你应该使用$q service。语法一模一样,基本上就是把“Promise”换成“$q”,去掉new关键字。
  • 假设那些get… 方法返回承诺,你应该写var p1 = $scope.getX1($scope.model[option][0][0].id); 等并省略任何new Promise 调用。如果不是,它们实际上是异步的吗?你在这里甚至需要承诺吗?

标签: javascript angularjs promise


【解决方案1】:

您永远不会解决承诺 1-4,因此对Promise.all(...).then 的“成功回调”永远不会触发。在给每个 Promise 的构造函数的回调中,使用每个 Promise 获取的数据调用 resolve

// ...
var p1 = new Promise((resolve, reject) => {
    resolve($scope.getX1($scope.model[option][0][0].id));
});
// ...

这就是你从 Promise 中“返回”数据的方式。详情请见this article

编辑:如果$scope.getX1本身返回一个Promise,你可以简单地将它分配给p1,即:

var p1 = $scope.getX1($scope.model[option][0][0].id);

【讨论】:

  • 我认为可以安全地假设 $scope.getX1 返回一个 $http 承诺。所以你真的应该将.then()getX1 联系起来,并将resolve/reject 放在$http 回调中。否则,您正在解析 promise 对象,而不是 promise 返回的数据,它对 OP 没有帮助。
  • 你说得很好。我添加了一个编辑来处理这种可能性。
  • 删除“如果它返回一个承诺”。如果没有,将值包装在 Promise.resolve 中也无济于事。
  • 有两件事让我感到困惑。首先,$scope.getX1 确实是一种旨在返回 $http 承诺的方法,因此我不必创建新的承诺......这让我看到了 $scope.getX1 函数并意识到还有另一个问题,函数永远不会返回承诺:apiService.getX1(id).then(function (response) { // Do stuff }); 变成:return apiService.getX1(id).then(function (response) { // Do stuff }); 谢谢大家!
  • 快速提示:如果您打算处理Promise.all 中的所有回复,我将暂缓在getX1 中调用.then.then 确实返回了一个承诺,所以它在技术上并没有被破坏,但是如果你过早地调用 .then,你可能会解决意外的数据。见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
  • 2016-10-13
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 2012-04-08
  • 2017-09-10
相关资源
最近更新 更多