Promises中的异步函数

时间:2017-03-16 08:32:40

标签: javascript promise es6-promise

以下是我的情况:

fetchData(foo).then(result => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(result + bar);
        }, 0)
    });
}).then(result => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve( result + woo);
        }, 0)
    });
}).then(result => {
    setTimeout(() => {
        doSomething(result);
    }, 0)
});

其中每个setTimeout都是使用回调模式的不同异步操作。

将每个函数包装在promise中真的很痛苦,我觉得代码看起来应该更像这样:

fetchData(foo).then(result => {
    setTimeout(() => {
        return result + bar;
    }, 0)
}).then(result => {
    setTimeout(() => {
        return result + woo;
    }, 0)
}).then(result => {
    setTimeout(() => {
        doSomething(result);
    }, 0)
});

显然这不起作用。

我使用Promise吗?我真的必须在promises中包装所有现有的异步函数吗?

编辑:

实际上我意识到我的例子并不完全代表我的情况,我没有说清楚我的例子中的setTimeout是为了重新发送异步操作。这种情况更能代表我的情况:

fetchData(foo).then(result => {
    return new Promise((resolve, reject) => {
        asyncOperation(result, operationResult => {
            resolve(operationResult);
        }, 0)
    });
}).then(result => {
    return new Promise((resolve, reject) => {
        otherAsyncOperation(result, otherAsyncResult => {
            resolve( otherAsyncResult);
        }, 0)
    });
}).then(result => {
        doSomething(result);
});

2 个答案:

答案 0 :(得分:3)

  

我使用Promise吗?我真的必须在promises中包装所有现有的异步函数吗?

是。是。

  

我觉得代码看起来应该更像这样

不,不应该。它应该看起来像这样:

function promiseOperation(result) {
    return new Promise((resolve, reject) => {
        asyncOperation(result, resolve, 0)
    });
}
function otherPromiseOperation(result) {
    return new Promise((resolve, reject) => {
        otherAsyncOperation(result, resolve, 0)
    });
}

fetchData(foo).then(promiseOperation).then(otherPromiseOperation).then(doSomething);
  

将每个函数包装在promise

中真的很痛苦

好吧,不要每次都重复写出来。您可以将此包装抽象为函数!

function promisify(fn) {
    return value => new Promise(resolve => {
        fn(value, resolve, 0)
    });
}
const promiseOperation = promisify(asyncOperation);
const otherPromiseOperation = promisify(otherAsyncOperation);
fetchData(foo).then(promiseOperation).then(otherPromiseOperation).then(doSomething);

请注意,大多数promise库都附带了这样的promisification函数,因此您的整个代码将减少到这三行。

答案 1 :(得分:0)

你正在使用诺言。关于第一段代码的一个小注释:您没有返回上一个then()回调的承诺:

...
}).then(result => {
    setTimeout(() => {
        doSomething(result);
    }, 0)
});

如果您只需要执行异步操作而不返回fetchData调用方最后一次异步操作的值,那么这是正确的。如果您需要返回此值,则还需要转换为承诺此操作:

fetchData(foo).then(result => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(result + bar);
        }, 0)
    });
}).then(result => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(result + woo);
        }, 0)
    });
}).then(result => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(doSomething(result));
        }, 0)
    });  
});

在这里,我认为doSomething同步函数,返回一个值。

这样说,如果你想减少创建承诺每次包裹setTimeout的噪音,你可以创建一个效用函数setTimeoutWithPromise

function setTimeoutWithPromise(operation, millisec) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(operation());
        }, millisec)
    });
}

清理你的代码:

fetchData(foo)
    .then(result => setTimeoutWithPromise(() => result + bar, 0))
    .then(result => setTimeoutWithPromise(() => result + woo, 0))
    .then(result => setTimeoutWithPromise(() => doSomething(result), 0));