编辑-尽管答案中包含几个可行的解决方案,但我要指出,Parse JS SDK 2.0(以及因此的Parse-Server 3.0)已经发布,实际上删除了Parse.Promise。因此,最好的解决方案是换出Parse Promise实现并改为使用本机Promises。
我使用Parse-Server(最新版本2.8.2)作为后端。我已经很习惯诺言,并且在我的代码中根深蒂固。
不过,我已经开始使用异步/等待模式。但这在我现有的所有实现中都不能很好地发挥作用。
此示例将引发错误:
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()
都用于传递回调函数。我在整个代码中都使用了此功能,并在重构某些功能以在添加新功能时使用异步/等待时发现了问题。
我理解问题在于异步函数将其结果包装在Promise中。因此,它将我的Parse.Promise
转换为没有.always()
方法的其他类型。
我是否有一种简单的方法可以替代async的功能以返回Parse.Promise?还是要使用异步/等待功能来重新处理always()
呼叫?
答案 0 :(得分:2)
您似乎无法更改从async
函数返回的承诺类型。它是内置的以返回本机承诺,并且不可配置。这里有一个类似的讨论,关于如何使async
函数返回Bluebird Promise here。结论是,如果要蓝鸟承诺,则不能这样做,必须包装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
});
或者,您可以包装异步函数以返回所需的Promise类型:
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。然后,您可以对.always()
函数返回的承诺使用async
。
答案 1 :(得分:0)
jfriend00的答案是可以接受的解决方案。 .catch(value => {return value}).then(...)
基本上将充当.always()
。
就我而言,我不想这样做,因为这意味着我在许多地方打补丁以解决源于一个的问题。我正在重做一个使用Parse.Promise
来使用async / await的现有函数,并且我还为其添加了一些功能。在完成之前,我没有发现.always()
问题。我不想简单地放弃返工并用诺言再次重做更新。
虽然草率,但我最终将自己的辅助函数包装在了自己的辅助函数中。原始的助手功能是 not 异步的,并基于异步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
);
});
这使我能够像以前一样调用原始的辅助函数,尽管实现已更新为更简洁,更易读。
但是,有一件事是我不能使用函数式编程,这是我最近一直在学习并试图付诸实践的。这不起作用:
const promiseErrorTestHelper = async (<same params>) => {
let returnPromise = new Parse.Promise();
promiseErrorTestHelperHelper(<same params>).then(
returnPromise.resolve,
returnPromise.reject
);
return returnPromise;
}
我的理解是,这实际上应该与上面的相同,只是没有被包裹在匿名函数中。当然,该变量没有命名,但是应该以任何一种方式传递给这些方法,对吗?我在其他地方使用了这种模式,尽管不是为了promise.resolve /拒绝,因为我直接将其返回。但是我对我的云函数有很多.then( response.success, response.error )
的调用,而不是像上面的工作示例那样将returnPromise.resolve
交换为response.success
,而将returnPromise.reject
交换为{{ 1}}。那些工作正常。