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

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

问题描述

我想履行一些其他承诺的承诺。关键是,我真的希望在第一个承诺得到满足后立即访问(仍在等待)第二个承诺。不幸的是,只有这两个承诺都满足,我似乎才能得到第二个承诺的解决方案价值。



这里是我想到的用例:

  var picker = pickFile(); 

picker.then(//等待用户选择一个文件
函数(downloadProgress){
//用户选择一个文件,该文件可能无法使用只是(例如,
//如果它必须通过网络下载),但是我们可以在
/ /背景

...做一些更多的用户交互...

返回downloadProgress;
}
).then(//等待
函数(文件){
//对文件执行某些操作
}

函数 pickFile 显示一个文件选择器,用户可以从他们自己的文件中选择一个文件硬盘驱动器或从URL。它返回一个承诺,一旦用户选择了一个文件,它就满足了选择器。在这一点上,我们可能仍然需要通过网络下载所选文件。因此,我不能将所选文件作为分辨率值实现选择器。相反,选择器应该通过另一个承诺 downloadProgress 来实现,而最终将会使用所选文件来实现。



对于完整的,以下是 pickFile 函数的模拟实现:

  function pickFile(){
...显示文件选择器...

var resolveP1 = null;

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

//假装用户选择一个文件的模拟器代码
window.setTimeout(function(){
var p2 = Promise.resolve('thefile');
resolveP1(p2); // <--- PROBLEM:我实际上想要用p2
}完成* p1,3000);

return p1;
}

标记行中的问题是我想要履行承诺 p1 与新的承诺 p2 ,但我只知道如何解决 实现和解决之间的区别是,首先检查是否提供的价值 p2 再次是一个承诺。如果是,则履行 p1 将被推迟直到 p2 履行,然后 p1 将满足 p2 的分辨率值而不是 p2 本身。



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

  resolveP1(p2); //< ---问题:我实际上想要通过p2 

第二个代码示例由

  resolveP1({promise:p2}); 

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

  return downloadProgress; 

by

  return downloadProgress.promise; 

但是,当我真正想要做的只是履行时,这似乎是一个黑客解决方案



我很感激任何建议。

解决方案

除了我已经在问题中描述的解决方法之外,似乎没有一个解决方案。为了将来参考,如果您希望履行(而不是解决)承诺 p ,其值为 val ,其中 val 是另一个承诺,然后只需调用 p 的承诺解决函数,参数 val 将无法正常工作。这将导致 p val 的状态锁定,这样一旦满足 val 将满足 val 的分辨率值(见< a href =http://www.ecma-international.org/ecma-262/6.0/#sec-promise-resolve-functions =nofollow> spec )。



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

  var resolveP; //承诺解决函数p 

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

函数fulfillPwithPromise(val){//履行p与承诺val
resolveP({promise:val});
}

p.then(function(res){
//一旦满足p就要做某事...

return res。承诺;
})然后(function(res){
//尽快执行第二个承诺...
});

如果您已经知道 val 是一个承诺。如果您不能对 val 的类型作出任何假设,那么您似乎没有运气。你必须永远在另一个对象中包含promise解析值,或者你可以尝试检测 val 是否有一个字段然后类型function,并有条件地包装。



这就是说,在某些情况下,promise解决方案的默认行为实际上可能有所需影响。因此,如果您确定您希望履行而不是解决第一个承诺,则仅使用上述解决方法。


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.

Here's the use case that I have in mind:

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.
    }
)

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.

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;
}

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.

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

from the second code example by

        resolveP1({promise: p2});

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

        return downloadProgress;

by

        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.

I'd appreciate any suggestions.

解决方案

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).

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...
});

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.

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天全站免登陆