用另一个承诺履行(不解决)承诺 [英] Fulfill (don't resolve) promise with another promise

查看:17
本文介绍了用另一个承诺履行(不解决)承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用一些其他的承诺来履行一个承诺.关键是我真的想在第一个承诺完成后立即访问(仍在等待)第二个承诺.不幸的是,我似乎只能在两个承诺都实现后才能获得第二个承诺的分辨率值.

I want to fulfill a promise with some other promise. The point is that I really want to get access to the (still pending) second promise as soon as the first promise is fulfilled. Unfortunately, I only seem to be able to get the second promise's resolution value once both both promises are fulfilled.

这是我想到的用例:

var picker = pickFile();

picker.then(  // Wait for the user to pick a file.
    function(downloadProgress) {
        // The user picked a file. The file may not be available just yet (e.g.,
        // if it has to be downloaded over the network) but we can already ask
        // the user some more questions while the file is being obtained in the
        // background.

        ...do some more user interaction...

        return downloadProgress;
    }
).then( // Wait for the download (if any) to complete.
    function(file) {
        // Do something with the file.
    }
)

函数 pickFile 显示一个文件选择器,用户可以在其中从自己的硬盘驱动器或 URL 中选择文件.它返回一个承诺 picker ,一旦用户选择了一个文件就会实现.此时,我们可能仍然需要通过网络下载所选文件.因此,我无法使用所选文件作为分辨率值来实现 picker.取而代之的是,picker 应该用另一个 promise 来实现,downloadProgress,它最终会用选定的文件来实现.

The function pickFile displays a file picker where the user may pick a file either from their own hard drive or from a URL. It returns a promise picker that is fulfilled as soon as the user has picked a file. At this point, we may still have to download the selected file over the network. Therefore, I cannot fulfill picker with the selected file as resolution value. Instead, picker should be fulfilled with another promise, downloadProgress, which in turn will eventually be fulfilled with the selected file.

为了完整起见,这里是 pickFile 函数的模拟实现:

For completenes, here's a mock implementation of the pickFile function:

function pickFile() {
    ...display the file picker...

    var resolveP1 = null;

    var p1 = new Promise(
        function(resolve, reject) {
            resolveP1 = resolve;
        }
    );

    // Mock code to pretend the user picked a file
    window.setTimeout(function() {
        var p2 = Promise.resolve('thefile');
        resolveP1(p2);  // <--- PROBLEM: I actually want to *fulfill* p1 with p2
    }, 3000);

    return p1;
}

标记行的问题是我想用新的promise p2fulfillpromise p1,但我只知道如何解决它.实现和解析之间的区别是解析首先检查提供的值 p2 又是一个承诺.如果是,那么 p1 的实现将被推迟到 p2 被实现,然后 p1 将被 p2 的分辨率值而不是 p2 本身.

The problem in the marked line is that I would like to fulfill the promise p1 with the new promise p2, but I only know how to resolve it. The difference between fulfilling and resolving is that resolving first checks if the supplied value p2 is again a promise. If it is, then fulfillment of p1 will be deferred until p2 is fulfilld, and then p1 will be fulfilled with p2's resolution value instead of p2 itself.

我可以通过围绕 p2 构建一个包装器来解决这个问题,即通过替换该行

I could work around this issue by building a wrapper around p2, i.e. by replacing the line

        resolveP1(p2);  // <--- PROBLEM: I actually want to *fulfill* p1 with p2

来自第二个代码示例

        resolveP1({promise: p2});

然后,在第一个代码示例中,我必须替换该行

Then, in the first code example, I'd have to replace the line

        return downloadProgress;

        return downloadProgress.promise;

但是当我真正想做的只是履行(而不是解决)承诺时,这似乎有点像黑客.

But this seems like a bit of a hack when all I really want to do is just fulfill (instead of resolve) a promise.

我很感激任何建议.

推荐答案

除了我在问题中已经描述的解决方法之外,似乎没有其他解决方案.为了将来参考,如果您想履行(而不是解决)具有值 val 的承诺 p,其中 val 是另一个承诺,那么仅使用参数 val 调用 p 的承诺解析函数不会按预期工作.它会导致 p 被锁定"在 val 的状态上,这样 p 将被 valval 得到满足,code> 的解析值(参见 规范).

There doesn't seem to be a solution apart from the workaround I already described in the question. For future reference, if you want to fulfill (rather than resolve) a promise p with a value val, where val is another promise, then just calling the promise resolution function for p with argument val won't work as expected. It would cause p to be "locked in" on the state of val, such that p will be fulfilled with val's resolution value once val is fulfilled (see spec).

相反,将 val 包装在另一个对象中并使用该对象解析 p:

Instead, wrap val in another object and resolve p with that object:

var resolveP;  // Promise resolution function for p

var p = new Promise(
    function(resolve, reject) {
        resolveP = resolve;
    }
);

function fulfillPwithPromise(val) {  // Fulfills p with a promise val
    resolveP({promise: val});
}

p.then(function(res) {
    // Do something as soon as p is fulfilled...

    return res.promise;
}).then(function(res) {
    // Do something as soon as the second promise is fulfilled...
});

如果您已经知道 val 是一个承诺,则此解决方案有效.如果您不能对 val 的类型做出任何假设,那么您似乎不走运.要么你必须总是将promise解析值包装在另一个对象中,或者你可以尝试检测val是否有一个function"类型的字段then" 并有条件地包装它.

This solution works if you already know that val is a promise. If you cannot make any assumptions about val's type, then you seem to be out of luck. Either you have to always wrap promise resolution values in another object, or you can try to detect whether val has a field then of type "function" and wrap it conditionally.

也就是说,在某些情况下,promise 解析的默认行为实际上可能会产生预期的效果.因此,仅当您确定要履行而不是解决第一个承诺与第二个承诺时,才使用上述解决方法.

That said, in some cases the default behavior of promise resolution may actually have the desired effect. So only use the workaround described above if you are sure that you want to fulfill instead of resolve the first promise with the second one.

这篇关于用另一个承诺履行(不解决)承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆