【问题标题】:Optimising a nested promise优化嵌套承诺
【发布时间】:2017-03-03 13:53:57
【问题描述】:

如何优化以下内容(即避免嵌套承诺)?它有效,但似乎我要继续嵌套承诺

代码首先验证并返回一个服务,然后将该服务提供给一个异步调用 api 以获取项目的函数,然后我将对项目做一些事情,可能会调用另一个包含异步调用的函数:

new Promise(function(resolve, reject) {
    auth.authenticate(resolve);
}).then(function(service) {
    console.log('service', service);
    new Promise(function(resolve, reject) {
        lineItems.getLineItems(service, resolve, reject);
    }).then(function(items) {
        console.log('returned line items');
        console.log(items);
    }).catch(function(err){
        console.log('error!', err);
    });
});

【问题讨论】:

  • 这段代码容易出错,因为你没有return第二个promise。

标签: javascript node.js es6-promise


【解决方案1】:

只需从then返回新的承诺:

new Promise(function(resolve, reject) {
    auth.authenticate(resolve);
}).then(function(service) {
    console.log('service', service);
    return new Promise(function(resolve, reject) {
        lineItems.getLineItems(service, resolve, reject);
    });
}).then(function(items) {
    console.log('returned line items');
    console.log(items);
}).catch(function(err){
    console.log('error!', err);
});

另外,如果你可以调整lineItems.getLineItems 来返回一个promise,它看起来更简洁:

new Promise(function(resolve, reject) {
    auth.authenticate(resolve);
}).then(function(service) {
    console.log('service', service);
    return lineItems.getLineItems(service);
}).then(function(items) {
    console.log('returned line items');
    console.log(items);
}).catch(function(err){
    console.log('error!', err);
});

【讨论】:

  • 那么以这种方式创建 Promise 并通过 resolve/reject 传递给函数是一种好习惯吗?还是首先让我调用的函数成为一个承诺更好?
  • 如果lineItems.getLineItems 是您设计的,IMO 将resolvereject 传递到那里是多余的。你最好让它只接受service 作为参数并返回一个承诺。所以你可以只用return lineItems.getLineItems(service); 而不是return new Promise(function(resolve, ...
  • 如果您可以将其添加到您的答案中,我会接受它:)
【解决方案2】:

我主要在函数的定义方式上看到了几个问题。这实际上来自代码中定义的异步函数的非标准签名。

如果 auth.authenticatelineItems.getLineItems 是您编写的,请更新这些函数以返回正确的 Promise。那么组成将是:

auth.authenticate()
    .then((service) => lineItems.getLineItems(service))
    .then((items)   => console.info('Items:',items))
    .catch((err)    => console.error(err));

如果auth.authenticate 和/或lineItems.getLineItems 是外部的,并且遵循标准的nodejs callbak/errback 样式,您可以包装这些函数以返回一个promise:

const authenticate = Promise.promisify(auth.authenticate, {context:auth});
const getLineItems = Promise.promisify(lineItems.getLineItems,{context:lineItems});

authenticate()
    .then(getLineItems)
    .then((items)   => console.info('Items:',items))
    .catch((err)    => console.error(err));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    相关资源
    最近更新 更多