将异步函数返回的promise类型更改为其他类型



Edit-虽然答案包含一些可行的解决方案,但我要指出的是,Parse JS SDK 2.0(以及Parse Server 3.0(已经发布,并且实际上删除了Parse.Promise。因此,最好的解决方案是换掉Parse Promise实现,转而使用本机Promise。

我使用Parse Server(最新版本,2.8.2(作为后端。我已经习惯了承诺,它们在我的代码中根深蒂固。

不过,我已经开始使用async/await模式。但它并不能很好地与我现有的所有实现配合使用。

这个例子将抛出一个错误:

const promiseErrorTestHelper = async () => {
return Parse.Promise.as();
}
Parse.Cloud.define('promiseErrorTest', async(req, res) => {
promiseErrorTestHelper().always(
res.success
);
});

这个很好用:

const promiseErrorTestHelper = async () => {
return Parse.Promise.as();
}
Parse.Cloud.define('promiseErrorTest', async(req, res) => {
promiseErrorTestHelper().then(
res.success
);
});

在ParseServer中,无论promise被拒绝还是被解析,.always()都用于传递回调函数。我在整个代码中都使用了这一点,并在重构一些函数以在添加新功能时使用async/await时发现了这个问题。

我认为问题在于异步函数将其结果封装在promise中。因此,它取我的Parse.Promise,并将其转换为一个没有.always()方法的不同类型。

有没有一种简单的方法可以让我覆盖async的功能,返回Parse.Promise?或者,如果我想使用async/await,我是否必须重新处理always()调用?

似乎无法更改从async函数返回的promise类型。它是内置的,用于返回本机promise,并且不可配置。关于如何使async函数返回Bluebird promise,这里也有类似的讨论。结论是你不能这样做,所以如果你想要一个Bluebird承诺,你必须包装async函数。


要在发生错误后继续,通常的方法是使用.catch()来记录错误并且不重新抛出,从而"处理"错误:

someFunc().catch(err => {
// handle the error, continue processing, changes promise chain to resolved
console.log(err);
return null;
}).then(() => {
// will always get called when original promise resolves or rejects
// somewhat like your .always
});

或者,您可以包装异步函数以返回您想要的承诺类型:

function wrapFunc(arg) {
return Parse.Promise.resolve(someAsyncFunc(arg))
}

然后,改为调用包装器函数。


我不确定我是否建议这样做,因为您正在修改全局可访问的Promise原型,这可能会影响其他代码,但您也可以在内置Promise中添加.always()

Promise.prototype.always = function(fn) {
return this.then(fn, fn);
}

这实际上与Parse使用的实现完全相同。然后,您可以对async函数返回的promise使用.always()

jfriend00的答案是可以接受的。CCD_ 12将基本上起到CCD_ 13的作用。

在我的情况下,我不想这样做,因为这意味着我要在许多地方修补代码,以修复源于其中一个地方的问题。我正在重新设计一个现有的函数,该函数使用Parse.Promises来使用async/await,并且我还添加了一些功能。直到做完之后,我才发现.always()问题。我不想简单地放弃返工并再次承诺更新。

虽然很草率,但我最终还是用自己的辅助函数包装了我的辅助函数。原始的helper函数是而不是async,并返回基于async helper helper函数的结果解析的promise。

const promiseErrorTestHelper = async (<same params>) => {
let returnPromise = new Parse.Promise();
promiseErrorTestHelperHelper(<same params>).then(
success => { returnPromise.resolve(success); },
error => { returnPromise.reject(error); }
);
return returnPromise;
}
const promiseErrorTestHelperHelper = async () => {
// This can return whatever, body and parameters
// copied in entirety from parent function
}
Parse.Cloud.define('promiseErrorTest', async(req, res) => {
promiseErrorTestHelper().then(
res.success
);
});

这使我能够像以前一样调用原始的helper函数,尽管实现被更新为更干净、更可读。

不过,有一点是我不会使用函数式编程,我最近一直在学习并尝试将其付诸实践。这不起作用:

const promiseErrorTestHelper = async (<same params>) => {
let returnPromise = new Parse.Promise();
promiseErrorTestHelperHelper(<same params>).then(
returnPromise.resolve,
returnPromise.reject
);
return returnPromise;
}

我的理解是,这应该与上面的内容基本相同,只是没有被封装在匿名函数中。当然,变量没有命名,但应该以任何一种方式传递到这些方法中,对吧?我在其他地方使用这个模式,但不是用于promise.resolve/reject,因为我只是直接返回它。但是,我对我的云函数有很多.then( response.success, response.error )调用,而不是像上面的工作示例中那样,用returnPromise.resolveresponse.success交换,returnPromise.rejectresponse.error交换。这些很好用。

相关内容

最新更新