承诺中的 if-else 流程(蓝鸟)

Posted

技术标签:

【中文标题】承诺中的 if-else 流程(蓝鸟)【英文标题】:if-else flow in promise (bluebird) 【发布时间】:2014-12-23 08:29:38 【问题描述】:

这是我的代码的简短版本。

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require("fs"));

if (conditionA) 
  fs.writeFileAsync(file, jsonData).then(function() 
    return functionA();
  );
 else 
  functionA();

两个条件都调用functionA。有没有办法避免其他情况?我可以fs.writeFileSync,但我正在寻找一个非阻塞的解决方案。

【问题讨论】:

Promise 是为异步任务控制而设计的。为什么要使用同步功能?您可以简单地检查writeFileAsync的返回值。 【参考方案1】:

我想你正在寻找

(conditionA 
  ? fs.writeFileAsync(file, jsonData)
  : Promise.resolve())
.then(functionA);

简称

var waitFor;
if (conditionA)
    waitFor = fs.writeFileAsync(file, jsonData);
else
    waitFor = Promise.resolve(undefined); // wait for nothing,
                                          // create fulfilled promise
waitFor.then(function() 
    return functionA();
);

【讨论】:

我想知道这是打字稿还是蓝鸟问题,但是当我只是简单地做Promise.resolve() 时,我收到一个错误error TS2349: Cannot invoke an expression whose type lacks a call signature. Type ' <U>(onFulfill?: (value: Object) => U | PromiseLike<U>, onReject?: (error: any) => U | PromiseLi...' has no compatible call signatures.Promise.resolve() 有效。有什么想法吗? @ahong 这是一个 Typescript 问题,告诉您它无法派生 Promise.resolve() 的类型 - 尝试 Promise.resolve(undefined) 或将其显式转换为您想要的任何内容。【参考方案2】:

您总是可以将Promise.all() 与条件函数一起使用

var condition = ...;

var maybeWrite = function(condition, file, jsonData)
    return (condition) ? fs.writeFileAsync(file, jsonData) : Promise.resolve(true);


Promise.all([maybeWrite(condition, file, jsonData),functionA()])
.then(function()
    // here 'functionA' was called, 'writeFileAsync' was maybe called
)

或者,如果您希望 functionA 仅在文件写入后调用,您可以分开:

maybeWrite(condition, file, jsonData)
.then(function()
    // here file may have been written, you can call 'functionA'
    return functionA();
)

【讨论】:

我对这种方法的唯一问题是可维护性。你签了名,因为你不得不“解开”事情。这是 Promise 链的好处之一——你的逻辑是线性的。【参考方案3】:

虽然这里的其他建议有效,但我个人更喜欢以下建议。

Promise.resolve(function()
  if (condition) return fs.writeFileAsync(file, jsonData);
())
.then()

它的缺点是总是创建这个额外的承诺(相当小的 IMO),但在我看来更干净。您还可以在 IIFE 中轻松添加其他条件/逻辑。

编辑

在实施这样的事情很长时间之后,我肯定已经改变了一些更清晰的东西。无论如何都会创建初始承诺,因此简单得多:

/* Example setup */

var someCondition = (Math.random()*2)|0;
var value = "Not from a promise";
var somePromise = new Promise((resolve) => setTimeout(() => resolve('Promise value'), 3000));


/* Example */

Promise.resolve()
.then(() => 
  if (someCondition) return value;
  return somePromise;
)
.then((result) => document.body.innerhtml = result);
Initial state
实际上,在您的情况下,它只是
if (someCondition) return somePromise;

在第一个 .then() 函数内部。

【讨论】:

以上是关于承诺中的 if-else 流程(蓝鸟)的主要内容,如果未能解决你的问题,请参考以下文章

Redis - 在带有承诺的事务中插入数组中的值(蓝鸟)

猫鼬承诺与蓝鸟和打字稿

蓝鸟承诺在快递路线解决

蓝鸟承诺未定义?

处理嵌套承诺的最佳方法(蓝鸟)[重复]

蓝鸟嵌套承诺与每个/传播