连锁承诺打电话

问题描述 投票:1回答:4

我需要连续执行这三个

return App.initAccount().then(App.bindEvents).then(App.render);

而App.initAccount():

  initAccount: async function() {

    console.log('Initializing account...');

    await web3.eth.getCoinbase(function(err, account) {
      if (err !== null) {
        throw err;
      }

      App.account = account;
      console.log('Account: ' + App.account);
    });
  }

和App.bindEvents(),App.render()只是普通的同步函数。但是我在控制台中得到了什么:

Initializing account...
Binding events
Rendering
Account: ***

请解释如何链接这些调用以等待返回异步函数

UPD。根据文档,我认为web3.eth.getCoinbase()返回一个Promise <\ String>,但结果证明这是不正确的。

javascript asynchronous promise
4个回答
2
投票

我想web3.eth.getCoinbase()不会返回一个承诺(所以你不会在这里等待任何事情。你需要在这样的承诺中包装函数调用:

await new Promise((resolve, reject) => {
  web3.eth.getCoinbase(function(err, account) {
      if (err !== null) {
        return reject(err)
      }

      App.account = account;
      return resolve(account)
    });
})

根据T.J建议编辑

在这种情况下,您实际上不需要initAccount作为异步函数,您可以将您的函数重构为:

initAccount: function() {
  return new Promise((resolve, reject) => {
    console.log('Initializing account...');

    web3.eth.getCoinbase(function(err, account) {
      if (err !== null) {
        return reject(err)
      }

      App.account = account;
      console.log('Account: ' + App.account);
      return resolve(account)
    });
  })
}

1
投票

从风格的角度来看,你最好不要在顺序流方面混合回调和异步/等待。要使用回调样式函数并使用async / await编织它们,您可以将它们包含在promises中以“隐藏”promises:

class Foo {
    initAccount() {
        return new Promise((resolve, reject) => {
            web3.eth.getCoinbase(function(err, account) {
                if (err !== null) {
                    reject(err);
                }
                resolve(account);
            });
        });
    }
}

const o = new Foo();
const account = await foo.initAccount();
// Then do bindEvents
// etc

0
投票

getCoinbase看起来不像是一个承诺的函数。您应该将其包装为按预期运行。

手动:

await new Promise((resolve, reject) => {
  web3.eth.getCoinbase(function(err, account) {
    if (err !== null) {
      reject(err);
    }

    App.account = account;
    console.log('Account: ' + App.account);
    resolve(account);
  });
});

或者使用像this这样的东西


0
投票

我怀疑web3.eth.getCoinbase没有回复承诺,因为你正在回复它。 await只等待承诺。

所以你可能需要将这个API包装在一个promise中,这意味着initAccount不需要是一个async函数,因为这是你需要new Promise的罕见情况之一:

initAccount: function() {
  return new Promise((resolve, reject) => {
    console.log('Initializing account...');

    web3.eth.getCoinbase(function(err, account) {
      if (err !== null) {
        reject(err);
      } else {
        App.account = account;
        console.log('Account: ' + App.account);
      }
    });
  });
}

另外,如果bindEventsrender同步完成他们的工作,你通常会把它们放在同一个then处理程序中:

return App.initAccount().then(() => {
  App.bindEvents();
  App.render();
});
© www.soinside.com 2019 - 2024. All rights reserved.