将异步函数返回的承诺类型更改为其他类型
Change type of promise returned by async functions to a different type
编辑 - 虽然答案包含几个可行的解决方案,但我要指出的是,Parse JS SDK 2.0(以及 Parse-Server 3.0)已经公布,并且实际上删除了 Parse.Promise。因此,最好的解决方案是换掉 Parse Promise 实现并改用本机 Promises。
我使用 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
);
});
在 Parse-Server 中,.always()
用于传递回调函数,无论承诺是被拒绝还是已解决。我在我的整个代码中都使用了它,并在重构一些函数以在添加新功能时使用 async / await 时发现了这个问题。
我理解问题在于异步函数将其结果包装在一个承诺中。因此,它将我的 Parse.Promise
转换为没有 .always()
方法的不同类型。
是否有一种简单的方法可以让我将异步功能覆盖为 return 和 Parse.Promise?或者,如果我想使用异步/等待,我是否必须重新处理 always()
调用?
您似乎无法更改 return 从 async
函数编辑的承诺类型。它内置于 return 原生承诺,不可配置。关于如何使 async
函数 return 成为 Bluebird 承诺 here,这里有类似的讨论。结论是你不能,所以如果你想要一个 Bluebird 承诺,你必须包装 async
函数。
要在错误后继续,通常的方法是使用 .catch()
记录错误并且不会重新抛出,因此 "handling" 错误:
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
});
或者,您可以将异步函数包装到 return 您想要的承诺类型:
function wrapFunc(arg) {
return Parse.Promise.resolve(someAsyncFunc(arg))
}
然后调用包装函数。
我不确定我是否推荐这个,因为您正在修改全局可访问的 Promise 原型,这可能会影响其他代码,但您也可以向内置 promise 添加 .always()
。
Promise.prototype.always = function(fn) {
return this.then(fn, fn);
}
这实际上是完全相同的实现 that Parse uses。然后,您可以在从 async
函数 return 编辑的承诺上使用 .always()
。
jfriend00 的回答是一个可以接受的解决方案。 .catch(value => {return value}).then(...)
基本上将作为 .always()
发挥作用。
就我而言,我不想这样做,因为这意味着我要在许多地方修补代码以解决源自一个地方的问题。我正在重新设计一个现有的函数,该函数使用 Parse.Promise
s 来使用 async / await,我也向它添加了一些功能。直到完成后我才发现 .always()
问题。我不想简单地扔掉返工并承诺再次重做更新。
虽然草率,但我最终将我的辅助函数包装在它自己的辅助函数中。原始的辅助函数 不是 异步的,return 是一个基于异步辅助-辅助函数的结果解决的承诺。
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
);
});
这使我能够像以前一样调用原始的辅助函数,尽管更新后的实现更加清晰易读。
不过,有一件事是我无法使用函数式编程,我最近一直在学习并尝试付诸实践。这没有用:
const promiseErrorTestHelper = async (<same params>) => {
let returnPromise = new Parse.Promise();
promiseErrorTestHelperHelper(<same params>).then(
returnPromise.resolve,
returnPromise.reject
);
return returnPromise;
}
我的理解是,这应该与上面的几乎相同,只是没有被包裹在匿名函数中。当然,变量没有命名,但应该以任何一种方式传递给那些方法,对吧?我在别处使用了这个模式,虽然不是 promise.resolve / reject 因为我只是直接 return 。但是我有很多 .then( response.success, response.error )
调用我的云函数,而不是做我在上面的工作示例中所做的 returnPromise.resolve
与 response.success
交换和 returnPromise.reject
与 [= 交换20=]。那些工作正常。
编辑 - 虽然答案包含几个可行的解决方案,但我要指出的是,Parse JS SDK 2.0(以及 Parse-Server 3.0)已经公布,并且实际上删除了 Parse.Promise。因此,最好的解决方案是换掉 Parse Promise 实现并改用本机 Promises。
我使用 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
);
});
在 Parse-Server 中,.always()
用于传递回调函数,无论承诺是被拒绝还是已解决。我在我的整个代码中都使用了它,并在重构一些函数以在添加新功能时使用 async / await 时发现了这个问题。
我理解问题在于异步函数将其结果包装在一个承诺中。因此,它将我的 Parse.Promise
转换为没有 .always()
方法的不同类型。
是否有一种简单的方法可以让我将异步功能覆盖为 return 和 Parse.Promise?或者,如果我想使用异步/等待,我是否必须重新处理 always()
调用?
您似乎无法更改 return 从 async
函数编辑的承诺类型。它内置于 return 原生承诺,不可配置。关于如何使 async
函数 return 成为 Bluebird 承诺 here,这里有类似的讨论。结论是你不能,所以如果你想要一个 Bluebird 承诺,你必须包装 async
函数。
要在错误后继续,通常的方法是使用 .catch()
记录错误并且不会重新抛出,因此 "handling" 错误:
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
});
或者,您可以将异步函数包装到 return 您想要的承诺类型:
function wrapFunc(arg) {
return Parse.Promise.resolve(someAsyncFunc(arg))
}
然后调用包装函数。
我不确定我是否推荐这个,因为您正在修改全局可访问的 Promise 原型,这可能会影响其他代码,但您也可以向内置 promise 添加 .always()
。
Promise.prototype.always = function(fn) {
return this.then(fn, fn);
}
这实际上是完全相同的实现 that Parse uses。然后,您可以在从 async
函数 return 编辑的承诺上使用 .always()
。
jfriend00 的回答是一个可以接受的解决方案。 .catch(value => {return value}).then(...)
基本上将作为 .always()
发挥作用。
就我而言,我不想这样做,因为这意味着我要在许多地方修补代码以解决源自一个地方的问题。我正在重新设计一个现有的函数,该函数使用 Parse.Promise
s 来使用 async / await,我也向它添加了一些功能。直到完成后我才发现 .always()
问题。我不想简单地扔掉返工并承诺再次重做更新。
虽然草率,但我最终将我的辅助函数包装在它自己的辅助函数中。原始的辅助函数 不是 异步的,return 是一个基于异步辅助-辅助函数的结果解决的承诺。
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
);
});
这使我能够像以前一样调用原始的辅助函数,尽管更新后的实现更加清晰易读。
不过,有一件事是我无法使用函数式编程,我最近一直在学习并尝试付诸实践。这没有用:
const promiseErrorTestHelper = async (<same params>) => {
let returnPromise = new Parse.Promise();
promiseErrorTestHelperHelper(<same params>).then(
returnPromise.resolve,
returnPromise.reject
);
return returnPromise;
}
我的理解是,这应该与上面的几乎相同,只是没有被包裹在匿名函数中。当然,变量没有命名,但应该以任何一种方式传递给那些方法,对吧?我在别处使用了这个模式,虽然不是 promise.resolve / reject 因为我只是直接 return 。但是我有很多 .then( response.success, response.error )
调用我的云函数,而不是做我在上面的工作示例中所做的 returnPromise.resolve
与 response.success
交换和 returnPromise.reject
与 [= 交换20=]。那些工作正常。