优化嵌套承诺

Optimising a nested promise

本文关键字:承诺 嵌套 优化      更新时间:2023-09-26

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

代码首先验证并返回一个服务,然后将该服务提供给一个函数,该函数异步调用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);
    });
});

返回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返回一个承诺,它看起来更简洁:

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是您编写的,请更新这些函数以返回正确的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风格,你可以包装这些函数来返回一个承诺:

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