首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何让JavaScript promise等待另一个promise在for()循环中被解析

如何让JavaScript promise等待另一个promise在for()循环中被解析
EN

Stack Overflow用户
提问于 2017-10-02 11:13:52
回答 2查看 1.1K关注 0票数 0

我有一个AngularJS应用程序,我使用它从firebase数据库中获取数据。

这是我的home-controller

代码语言:javascript
复制
$scope.wallets;

walletDAO.getWalletsByUserId(auth.uid)
.then(function(wallets){
    $scope.wallets = wallets;
    $scope.$apply();
})
.catch(function(error){
    console.log(error);
});

这是我在称为walletDAO的服务中的两个方法

代码语言:javascript
复制
this.getWalletsByUserId = function(id) {
    return new Promise(function(resolve, reject) {
        //codigo aqui
        var dbRef = database.ref("users/" + auth.currentUser.uid);
        dbRef.on('value', function(data) {
            //console.log("Wallet IDs Retrieved!");
            var userOnDB = data.val();
            var walletIds = userOnDB.wallets;
            var wallets = [];
            for (i = 0; i < walletIds.length; i++) {
                var x = getWalletById(walletIds[i])
                .then(function(wallet){
                    wallets.push(wallet);
                })
                .catch(function(error){
                    console.log(error);
                });
            }
            resolve(wallets);
        }, function(error) {
            reject(error);
        });
    });
};

var getWalletById = function(id) {
    return new Promise(function(resolve, reject) {
        var dbRef = database.ref("wallets/" + id);
        dbRef.on('value', function(data) {
            //console.log("Wallet Retrieved!");
            var wallet = data.val();
            //console.log(wallet);
            resolve(wallet);
        }, function(error) {
            reject(error);
        });
    });
};

第二个方法getWalletById接收一个wallet ID并从firebase数据库返回一个wallet对象。此方法在第一个方法( for循环内的getWalletsByUserId )上调用,该方法应等待第二个方法返回钱包,然后再迭代到下一个方法,以便将其推入数组。问题是它不等待,代码在解析getWalletById之前在home-controller上执行.then()方法,留下空的$scope.wallets

有什么建议吗?

EN

回答 2

Stack Overflow用户

发布于 2017-10-02 20:59:59

使用$q.all()等待所有子承诺完成

代码语言:javascript
复制
$q.all(walletIds.map(function(id){
  return getWalletById(id);
})).then(function(wallets){
  ...
})
票数 1
EN

Stack Overflow用户

发布于 2017-10-03 00:14:37

不是从ref.on方法生成ES6 promise,而是使用ref.once方法并通过$q.when将其放入AngularJS执行上下文中

代码语言:javascript
复制
function getWalletById(id) {
    var dbRef = database.ref("wallets/" + id);
    var es6Promise = dbRef.once('value');
    return $q.when(es6Promise);
}

只有在AngularJS执行上下文中应用的操作才能从AngularJS数据绑定、异常处理、属性监视等中受益。

在父函数中使用$q.allpromise chaining

代码语言:javascript
复制
this.getWalletsByUserId = function(id) {
    var dbRef = database.ref("users/" + auth.currentUser.uid);
    var es6Promise = dbRef.once('value')
      .then(function(snapshot)
        //console.log("Wallet IDs Retrieved!");
        var userOnDB = snapshot.val();
        var walletIds = userOnDB.wallets;
        var promiseList = walletIds.map(function(id){
            return getWalletById(id);
        });
        return $q.all(promiseList);
    });
    return $q.when(es6Promise);
};

.then方法返回一个新的promise,该promise通过successCallback的返回值errorCallback解析或拒绝(除非该值是promise,在这种情况下,它是使用promise chaining在promise中解析的值解析的)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46519018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档