Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 理解JS承诺_Javascript_Promise - Fatal编程技术网

Javascript 理解JS承诺

Javascript 理解JS承诺,javascript,promise,Javascript,Promise,我想更深入地了解承诺是如何在内部发挥作用的。 因此,我有一些示例代码: var p1=新承诺( 功能(解析、拒绝){ window.setTimeout( 函数(){ 解析('rescalled') }, 2000); }); var p2=新承诺( 功能(解析、拒绝){ window.setTimeout( 函数(){ 解析('rescalled') }, 2000); }); 函数(){ 返回p1.then(函数(val){ 控制台日志(“p1”); 返回p2.then(函数(val){ 控

我想更深入地了解承诺是如何在内部发挥作用的。 因此,我有一些示例代码:

var p1=新承诺(
功能(解析、拒绝){
window.setTimeout(
函数(){
解析('rescalled')
}, 2000);
});
var p2=新承诺(
功能(解析、拒绝){
window.setTimeout(
函数(){
解析('rescalled')
}, 2000);
});
函数(){
返回p1.then(函数(val){
控制台日志(“p1”);
返回p2.then(函数(val){
控制台日志(“p2”);
返回val;
});
});
}
chainPromises().then(函数(val){
控制台日志(val);
});
这里是一个执行此代码的示例

正如您所预测的,首先解析p1,然后解析p2,最后最后打印resolv值

但API ref规定如下:

promiseReturning().then(function(){
    alert(1);
    return foo(); // foo returns a promise
}).then(function(){
    alert(2); // will only run after the ENTIRE chain of `foo` resolved
              // if foo OR ANY PART OF THE CHAIN rejects and it is not handled this 
              // will not run
});
“then”返回一个与您从中返回的值相等的新承诺 通过Promise.resolve传递后OnCompleted/onRejected

因此,了解“then”函数的确切执行时间会很有趣吗? 因为代码中的最后一个“then”链接到chainPromises(),所以我首先想到 它将在函数chainPromissions()返回某些内容(在本例中为另一个承诺)后执行

如果是这种情况,那么最终“then”函数的“val”将是返回的承诺。 但是,最终的“then”将等待,直到返回的第一个“then”中的所有承诺都得到解决。 这绝对是有道理的,因为通过这种方式,“then”函数可以堆叠,但是 我真的不明白这是怎么做到的,因为API规范没有真正涵盖“then”返回的内容以及“then”函数的执行时间

或者换句话说,为什么最终的“then”函数要等到所有承诺都在chainPromissions()函数中解析,而不是像API文档所说的那样,只等待第一个返回的对象


我希望我能弄清楚我的意思……)

让我们从一个简单的角度开始:“chainPromises”返回一个承诺,因此您可以这样看:

// Do all internal promises
var cp = chainPromises();

// After everything is finished you execute the final "then".
cp.then(function(val) {
    console.log(val);
});
一般来说,当从“then”子句中返回一个承诺时,只有在内部“then”完成之后,封装承诺的“then”功能才会标记为完成

因此,如果“a”是承诺,“b”是承诺:

// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.  
var c = a.then(function () {
    return b.then(function () {
        console.log("B!");
    };
};

// c is a promise, since "then" always returns a promise.    
c.then(function() {
    console.log("Done!");
};
因此,输出将是:

B! 
Done!
请注意,如果您不“返回”内部承诺,则不会出现这种情况:

// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.  
var c = a.then(function () {
    // Notice we're just calling b.then, and don't "return" it. 
    b.then(function () {
        console.log("B!");
    };
};

// c is a promise, since "then" always returns a promise.    
c.then(function() {
    console.log("Done!");
};

在这里,我们无法知道将首先输出什么。它可以是“B!”或“Done!”。

我不知道在实际的promises库中是如何实现的,但我能够通过以下方式重新创建此功能: 1) 每个承诺都有一个waitingPromises属性; 2) 然后方法返回一个新的承诺,并且原始承诺的waitingPromises属性指向新承诺


通过这种方式,.then()s链创建了一个类似于链表或树的结构(每个承诺可以有几个等待承诺)。承诺只有在其“父”承诺得到解决后才能得到解决。.then方法本身会立即执行,但它创建的相应承诺只会在以后解决。 我不确定这是否是一个好的解释,我希望了解其他可能的方法。

关于承诺解决方案 您在这里看到的东西被称为递归
然后
可解析。承诺/A+规范中的承诺解决流程包含以下条款:

OnCompleted或onRejected返回一个值x,运行承诺解决过程[[Resolve]](promise2,x)

ES6承诺规范(承诺展开)包含类似的条款

这要求当发生
resolve
操作时:在承诺构造函数中,通过调用
promise.resolve
或在
中,然后
链接承诺实现必须递归地打开返回值(如果它是承诺)

实际上 这意味着,如果
oncompleted
(the
then
)返回一个值,则尝试自己“解析”承诺值,从而递归地等待整个链

这意味着:

promiseReturning().then(function(){
    alert(1);
    return foo(); // foo returns a promise
}).then(function(){
    alert(2); // will only run after the ENTIRE chain of `foo` resolved
              // if foo OR ANY PART OF THE CHAIN rejects and it is not handled this 
              // will not run
});
例如:

promiseReturning().then(function(){
    alert(1);
    return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
    alert("This will never run");
});
而且:

promiseReturning().then(function(){
    alert(1);
    return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
    alert("This will only run after 2000 ms");
});
这是个好主意吗? 在promises规范过程中,这是一个备受争议的话题。第二个链式方法虽然没有表现出这种行为,但被讨论过,但被决定反对(在Chrome中仍然可用,但很快将被删除)。你可以了解整个辩论此行为是出于实用原因,因此您不必手动执行

用其他语言
值得一提的是,其他语言并没有做到这一点,Scala中的未来或C#中的任务都没有这一特性。例如,在C#中,您必须调用
任务。对任务展开
,以等待其链解析。

Promise
然后返回
Promise对象
,而不是
Promise的解析值
。我用叉子叉了你的叉子,加了一些我的叉子


promise。然后在解析
promise对象之后立即执行

请检查以下示例,了解
promises
的工作原理:

The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
console.log('person1:shoe-ticket');
控制台日志(“人员2:鞋票”);
const promiseGirlfriendBringtickets=新承诺((解决,拒绝)=>{
设置超时(()=>{
决议(“票证”);
}, 3000);
});
PromiseGirlfriendBringtickets.然后((t)=>{
log(`person3:show${t}`);
})
控制台日志(“人员4:鞋票”);

控制台日志(“人员5:鞋票”)通常代码是同步的-一条语句执行就像(fileopen)一样,并且可以保证下一条语句将在之后立即执行,就像filewrite()