有条件地在另一个承诺中调用承诺

Calling promise in another promise, conditionally

这基本上是我的代码,使用 q:

let d = Q.defer();
let result = {
    name: 'peter'
};

d.resolve(result);
return d.promise;

但是,我现在需要根据特定条件执行一个步骤。此步骤调用另一个对象,该对象也是 returns 一个承诺。所以我有嵌套的承诺,如果这是正确的术语。

像这样:

let d = Q.defer();
let result = {
    name: 'peter'
};

if (someParameter) {
    otherService.getValue() // Let's say it returns 'mary'
        .then((res) => {
            result.name = res;
        });
}

d.resolve(result);
return d.promise;

但这不起作用(name 属性 仍然是 'peter')。大概是因为我内心的约定是迟早要解决的吧?

我也试过这个,但是如果我调用 returns 一个 promise 的 otherService 是行不通的。如果我只设置值,它确实有效:

let d = Q.defer();
let result = {
    name: 'peter'
};

d.resolve(result);
return d.promise
    .then((data) => {
        if (someParameter) {
            // Works
            data.name = 'john';

            // Doesn't work
            otherService.getValue()
                .then((res) => {
                    data.name = res;
                });
        }

        return data;
    });

此处的名称将是 'john',而不是 'mary'。

显然我误解了承诺,但我无法理解它。

使用 Promises 的控制流是...有趣?

无论如何,您就快完成了,您可以在 Promise 中嵌入 Promise 并将它们链接起来。但是,如果要嵌入它们,则必须 return 嵌入 Promise 链:

let d = Q.defer();
let result = {
    name: 'peter'
};

d.resolve(result);
return d.promise
    .then((data) => {
        if (someParameter) {

            // Should work now that we return the Promise
            return otherService.getValue()
                .then((res) => {
                    data.name = res;
                    // And we have to return the data here as well
                    return data;
                });
        }

        return data;
    });

Promise resolve 可以取一个值或另一个 Promise 并且它将处理流。因此,当我们在 thenreturn 时,我们返回的值可以是另一个 Promise 或只是一个值。机器会帮我们拆包。

不推荐使用 deferreds。如果有的话,您应该使用 Q.Promise 构造函数,但您甚至不需要它。只需使用 Q function 创建一个实现您的价值的承诺。

现在您可以(并且应该)将代码简化为

let d = someParameter ? otherService.getValue() : Q('peter');
return d.then(res => ({
    name: res
}));