简体   繁体   English

JS承诺 - 链阶段之前的链返回结束

[英]JS Promises - End of Chain Returning before Chain Step

I have a promise chain that consists of database queries and API calls. 我有一个包含数据库查询和API调用的promise链。 I am trying to run these processes and then store them as objects that I can use in my views, but it appears that my chain is rendering the last step faster than the value can be pulled from the stripe.customers.retrieve portion, which is preventing me from restoring the object returned by that method. 我正在尝试运行这些进程,然后将它们存储为我可以在我的视图中使用的对象,但看起来我的链正在渲染最后一步比从stripe.customers.retrieve部分提取的值更快,这是阻止我恢复该方法返回的对象。 See terminal output section for example. 例如,请参见端子输出部分。 It might be my misunderstanding of Promises, but shouldn't chaining call the items in a top to bottom order? 这可能是我对Promises的误解,但是不应该链接从上到下的顺序调用这些项目? Is there a way to prevent the last chain from rendering before the stripe.customers.retrieve finishes? 有没有办法阻止最后一个链在stripe.customers.retrieve完成之前呈现?

Promise chain: 承诺链:

var account;
var card;
var customerInfo;
var test;

models.Account.findOne({
    ...
}).then(function(_account){
    console.log('Here is the account: ' + _account);
    account = _account;
    return stripe.customers.retrieveCard(account.customerId, account.cardId, {
        function(err, account){
            if (err){
                return console.log(err);
            } else {
                return console.log(account);
            }
        }
    }).then(function(_card){
        console.log('Here is the card: ' + _card);
        card = _card;
        return stripe.customers.retrieve(account.customerId, function(err, customer){
            if (err){
                return console.log(err);
            } else {
                return console.log('Customer is returned ' + customer)
            }
        }).then(function(_customer){
            customerInfo = _customer;
            console.log('Returned value ' + _customer);
            console.log('Current card' + card);
            console.log('Current customer ' + customerInfo);
            res.render('pages/app/settings-billing.hbs', {
                ...
            });
        });
    });
}).catch(function(err){
    console.log(err);
});

Terminal Output: 终端输出:

Here is the account: [object SequelizeInstance:account]
Here is the card: [object Object]
Returned value undefined
Current card[object Object]
Current customer undefined
Customer is returned [object Object]

Here is the answer: You need to call your promises in the way you are expecting your return values. 答案就是:您需要按照预期返回值的方式来表达您的承诺。 What you were doing wrong is that you have nesting promises. 你做错了是你有嵌套的承诺。 The idea behind is that you invoke a promise and when it's fulfilled resolve the value. 背后的想法是你调用一个承诺,当它完成时解决了价值。

models.Account.findOne({
    ...
})
.then(function(_account){
    console.log('Here is the account: ' + _account);
    account = _account;

    return stripe.customers.retrieveCard(account.customerId, account.cardId, {
        function(err, account){
            if (err){
                return console.log(err);
            } else {
                return console.log(account);
            }
        }
    });
})
.then(function(_card){
     console.log('Here is the card: ' + _card);
     return stripe.customers.retrieve(account.customerId, function(err, customer){
         if (err){
                return console.log(err);
            } else {
                return console.log('Customer is returned ' + customer)
            }
        });
})
.then(function(_customer){  
                customerInfo = _customer;
            console.log('Returned value ' + _customer);
            console.log('Current card' + card);
            console.log('Current customer ' + customerInfo);
            res.render('pages/app/settings-billing.hbs', {
                ...
            });
}).catch(function(err){
    console.log(err);
});

Use then() on each stripe method instead of callback so you return a promise from each. 在每个条带方法上使用then()而不是回调,因此您可以从每个方法返回一个promise。

Have modified this a bit to keep passing one object through to the end instead of using global variables 已经修改了一点,以便将一个对象传递到最后,而不是使用全局变量

models.Account.findOne({
    ...
  })
  .then(function(_account) {
    let data = {
      account: _account
    }
    return stripe.customers.retrieveCard(_account.customerId, _account.cardId).then(function(card) {          
      data.card = card;
      return data;
    });
  })
  .then(function(data) {
    console.log('Here is the card: ' + data.card);
    return stripe.customers.retrieve(data.account.customerId).then(function(customer) {
      data.customer = customer;
      return data
    });
  })
  .then(function(data) {
    console.log(JSON.stringify(data, null, ' '));

  }).catch(function(err) {
    console.log(err);
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM