使用异步javascript时,每个第二个函数都是这样的:
function_name()
{
return new Promise((resolve,reject) => {
// do some async task
resolve();
});
}
即使使用es6 async / await我也无法避免“返回新Promise((resolve,reject)=> {...”这一部分。
是否有另一种编写此类代码的方法而没有所有重复的行?
感谢。
答案 0 :(得分:3)
首先,您应该避免围绕已经返回承诺的其他函数包含新约束的promise anti-pattern。如果您正在这样做,那么您可以完全停止这样做,只返回您的异步操作已经创建的承诺。这将立即简化事情。
如果你有旧的基于回调的未经过规则化的操作,那么一般来说,你应该只使用一次基本异步函数,然后只使用返回一个promise的函数版本进行编码。然后,您的所有逻辑流程都使用了promises,您将不会在代码的常规流程中看到new Promise(...)
样板。
此外,您通常可以避免这些天手动宣传。如果您正在使用node.js,则可以使用util.promisify()
在node.js调用约定之后创建任何异步函数的promisified版本。
或者,如果您使用Bluebird承诺库,您可以使用Promise.promisify()
宣传单个功能,也可以使用Promise.promisifyAll()
宣传整个界面。
使用这些替代方法中的任何一种都可以避免您看到反对的样板。
但是,如果您要自己从头开始手动宣传每个函数而不使用任何其他辅助函数,那么就无法避免使用new Promise(...)
语法。这就是它需要的。
因此,您的大多数编码不应涉及new Promise(...)
。如果确实如此,那么您需要向我们展示一些示例,我们可以提供更好/不同的编码方式。
答案 1 :(得分:0)
正在阅读评论并希望澄清:
你应该如何编写以下简单函数test(){return new Promise((resolve,reject)=> {setTimeout(()=> {resolve(42);});}); }
这看起来像是一个立即解决到42的承诺,所以你可以:
const test = _=>Promise.resole(42);
如果您希望在特定时间解析并多次使用的承诺,您可以写下以下内容:
const later = time => value =>
new Promise(
(resolve,reject)=>
_=>resolve(value),
time
);
const afterOneSecond = later(1000);
afterOneSecond("resolves after one second");
如果您想稍后拒绝某事:
later(1000)(Promise.reject("rejects after one second"));
如果您正在使用真实的承诺进行测试而不是嘲笑的承诺,并且需要在没有控制台警告您的情况下传递被拒绝的承诺并且未按照"未授权"你可以做的断点:
const p = Promise.reject("rejects after one second");
p.catch(ignore=>ignore);//catch it
later(1000)(p);//pass promise without catch to later
如果你有一个函数可以返回某个东西的承诺并处理你可以做的那个值。
myFunction()
.then(
something=>something.data
)
.then(
data=>...
)
如果你想检查something.data是否为空,如果你想拒绝,你可以这样做:
myFunction()
.then(
something=>
(something&&something.data.length!==0)
? something.data
: Promise.reject("Data cannot be empty")
)
.then(
data=>...
)
.catch(
e=>
(e==="Data cannot be empty")
? "do something special"
: Promse.reject(e)//keep rejecting, other error
);
如果您有一个可以抛出的同步函数,它是您的承诺链中的第一个函数,并且您希望它抛出的内容最终被拒绝承诺您可以执行以下操作:
const syncFunctionThatThrows = arg => {
if(arg===1){
throw "arg cannot be 1";
}
return arg;
};
//starting promise chain with synchronous function that can throw
// if it throws the error is absorbed by the chain and produces
// a rejected promise
Promise.resolve(1)//going to pass 1 to syncFunctionThatThrows
.then(syncFunctionThatThrows);
要使用回调api作为承诺,您可以这样做:
const asPromise = object => fn => args =>
new Promise(
(resolve,reject)=>
fn.apply(
object,
args.concat([
(...result)=>
(result[0])//first argument of callback is error
? reject(result[0])//reject with error
: resolve(result.slice(1,result.length))//resolve with result(s)
])
)
);
const callbackApiObjectAsPromise = asPromis(callbackApi);
callbackApiObjectAsPromise(callbackApi.someMethod)(["arg1","arg2"])
.then(
result=>...
)
//example of mysqljs
const connectionAsPromise = asPromise(connection);
connectionAsPromise(connection.query)([
'SELECT * FROM `books` WHERE `author` = ?',
['David']
]).then(
([results, fields])=>...
);
如果您没有进入diy,可以使用Pointy建议的promisifyAll或promisify。
答案 2 :(得分:0)
这可能是旧的,但我会给出我的答案,因为它可能会帮助一些迷失的灵魂。 首先你需要定义全局函数(我使用 globals. 对于 nodejs,可以设置为任何全局对象,如 window. 对于浏览器)
global.res= function (v){
return new Promise(function(r){r(v);});
}
global.rej= function (v){
return new Promise(function(r,rr){rr(v);});
}
然后你可以像这样在你的代码中使用 res/rej:
async function testing(param){
return param < 10 ? res(true) : rej(false)
}
console.log(await testing(2)) // shows 'true'
console.log(await testing(20)) // throws error with 'false' as value