优化嵌套的承诺

Optimising a nested promise

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

代码首先验证和 returns 一个服务,然后将该服务提供给一个函数,该函数异步调用 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 来自 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调整成return一个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);
});

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

如果 auth.authenticatelineItems.getLineItems 是您编写的,请将这些函数更新为 return 适当的 Promise。那么组成将是:

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

如果 auth.authenticate and/or lineItems.getLineItems 是外部的,并且遵循标准的 nodejs callbak/errback 风格,你可以将这些函数包装到 return 一个承诺中:

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));