javascript 返回新的承诺:简短的语法



当使用异步javascript时,每隔一个函数看起来像这样:

function_name()
{
return new Promise((resolve,reject) => {
// do some async task
resolve();
});
}

即使使用 es6 异步/等待,我也无法避免"返回新承诺((解析,拒绝)=> { ..."部分。

有没有另一种方法可以在没有所有这些重复行的情况下编写这样的代码?

谢谢。

首先,你应该避免使用promise反模式,它将新的promise包裹在已经返回promise的其他函数周围。 如果你正在这样做,那么你可以完全停止这样做,只返回你的异步操作已经创建的承诺。 这将立即简化事情。

如果您有未承诺的基于回调的旧式操作,那么通常,您应该只承诺一次基本异步函数,然后仅使用返回 promise 的函数版本进行编码。 然后,您的所有逻辑流都使用 promise,您将不会在代码的常规流中看到new Promise(...)样板。

此外,这些天您通常可以避免手动承诺。 如果您使用的是 node.js,则util.promisify()可用于按照 node.js 调用约定创建任何异步函数的 promisized 版本。

或者,如果您使用 Bluebird promise 库,您可以使用Promise.promisify()承诺单个函数,也可以使用Promise.promisifyAll()承诺整个接口。

使用这些替代方法中的任何一种都可以避免您似乎反对的样板文件。

但是,如果您要自己从头开始手动承诺每个函数,并且不使用任何其他帮助程序函数,则无法避免new Promise(...)语法。 这就是它所需要的。


所以,你的大部分编码不应该涉及new Promise(...)。 如果是这样,那么您需要向我们展示一些您的示例,我们可以建议更好/不同的编码方式。

正在阅读评论并想澄清一下:

你应该如何编写下面的简单函数 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,你可以使用promisifyAll或Promisify,如Pointy建议的那样。

这可能很老了,但我会提出我的答案,因为它可能会帮助一些迷失的灵魂。 首先,您需要定义全局函数(我正在使用全局函数。 对于nodejs,可以设置为任何全局对象,如窗口。

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

相关内容

最新更新