javascript 返回新的 Promise:短语法

新手上路,请多包涵

使用异步 javascript 时,每个第二个函数如下所示:

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

即使使用 es6 async/await,我也无法避免“return new Promise((resolve,reject) => { …”部分。

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

谢谢。

原文由 David Vielhuber 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 333
2 个回答

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

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

此外,现在您通常可以避免手动承诺。如果您使用的是 node.js,那么 util.promisify() 可用于创建遵循 node.js 调用约定的任何异步函数的承诺版本。

或者,如果您使用 Bluebird promise 库,您可以使用 Promise.promisify() 来 promisify 一个单独的函数,或者您可以使用 Promise.promisifyAll() 来 promisify 整个接口。

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

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


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

原文由 jfriend00 发布,翻译遵循 CC BY-SA 4.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
);

如果您有一个可以抛出的同步函数,它是您的 promise 链中的第一个函数,并且您希望它抛出的内容以被拒绝的 promise 结束,您可以执行以下操作:

 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 或按照 Pointy 的建议使用 promisify

原文由 HMR 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏