Javascript基本之-Promise

转载自: http://www.lht.ren/article/3/

Promise是什么呢?依据ecma-262的定义:

Promise是一个被用于延时盘算的终究效果的占位符

(A Promise is an object that is used as a placeholder for the eventual results of a deferred (and possibly asynchronous) computation.)

这个怎样明白呢

比如说,我要去麦当劳买点吃的,下单今后人家会先给你一个定单号,等人家外卖做好了,会提醒你,并用谁人定单小票来调换你真正的食品,在这时刻,谁人定单小票就是你这顿饭的占位符。

回到Promise,它有三种状况,分别为完成,谢绝和待决定,

而待决定的状况代表它还没有被完成或许是谢绝,也就是说,如果它一向都是处于待决定的状况,意味着代码永久都不会继承往下实行

所以下面这段代码永久都实行不到finish

new Promise((resolve, reject) => {
  console.log('waiting');
  document.writeln('waiting');
}).then((msg) => {
  console.log('finish');
});

也就是意味着,必需显现的实行resolve()或许是reject,递次才会继承往下实行。

那怎样处置惩罚这个题目呢,实在很简单,决定一下就好了嘛,哈哈~~

或许给Promise设置一个超时时候,看下面的代码:

function timeoutPromise(delay) {
  return new Promise( function(resolve,reject){
    setTimeout( function(){
      reject( "Timeout!" );
    }, delay );
  } );
}
Promise.race([
  new Promise(() => {
    console.log('waiting...');
  }),
  timeoutPromise(3000)
]).catch((msg) => {
  console.log(msg);
})

这段代码呢,会先守候5秒,然后会打印出一个毛病”Timeout”,在这里,Promise.race()现实上就是竞态的,谁先决定,其他的就会被扬弃。所以我们三秒钟后决定一个谢绝,剩下谁人promise自动被扬弃了

说到毛病处置惩罚了,思索下面的代码:

new Promise((resolve, reject) => {
  foo.bar();
}).then((msg) => {
  console.log(msg);
}, null).then((msg) => {
  console.log(msg);
}, (err) => {
  console.log(err);
});

这段代码,很明显foo不是对象,所以会报ReferenceError,所以呢,会自动决定为reject,然后他紧接着的谁人then没有谢绝处置惩罚回调,然后接着往下通报毛病,直到有reject回调为止,如果一向都没有reject回调呢,他就会在全局抛出一个未捕捉的非常。

那末如果在Promise决定屡次呢,现实上只要第一次决定见效,也就是说,只能有一种决定见效,又胜利又失利,或许胜利屡次,失利屡次听着就不靠谱是吧,思索下面的代码

new Promise((resolve, reject) => {
  resolve();
  reject();
  console.log('exec finish');
}).then((msg) => {
  console.log('resolve');
}, (err) => {
  console.log('reject');
});

运转效果是输出exec finish 和resolve,因为第一次决定为resolve, 所以reject决定就被扬弃了

人人想一下,决定后对应的then内里的回调函数是同步照样异步的呢,思索下面这个题目:

console.log(0);
let p = new Promise((resolve, reject) => {
  console.log(1);
  resolve();
  console.log(2);
})
console.log(3);
p.then((msg) => {
  console.log(4);
});
console.log(5);

他的效果是 1 2 3 5 4

答案很显然啦,是异步的!现实受骗决定今后,就会把它放到一个异步行列里挪用

那为何要这么设想呢,会给我们带来什么优点呢,思索下面这个题目

function getResult() {
  console.log(a);
}
function opt() {
  if (isAsync) {
    setTimeout(() => {
      getResult();
    }, 0);
  } else {
    getResult();
  }
}
var a = 0;
var isAsync = false;
opt();
a++;
isAsync = true;
opt();
a++;

他的效果输出的是0 2,那为何不是0, 1,现实上就是因为因为同步和异步的的不确定性致使的,也叫zalgo,所以呢,要想消弭他们的不确定性,必需就让他内里的代码要么都是同步,要么都是异步,这也是then为何是异步的缘由了

关于then,另有一个题目,就是then的返回值是什么,来继承看题目

var p = Promise.resolve( 21 );
var p2 = p.then( function(v){
  return v * 2;
});
console.log(p2);

经由历程他的效果,你很轻易就能够看出来,then的返回值是一个Promise,那末,这个then回调是否是能够这么明白呢?

function callback() {
  return Promise.resolve(42);
}

如果是的话,那末我们就研究一下Promise.resolve()的特征,然后then()同理就能够是吧

那末我们如今就研究一下Promise.resolve()的一些特征:

如果向Promise.resolve()通报一个非Promise,非thenable的马上值,就会马上获得这个值添补的Promise,这个有三个关键字,非Promise,非thenable和马上值

如果向Promise.resolve()通报一个真正的promise,那末就会返回这个Promise,又一个例子,很好明白

var p = Promise.resolve(42);
var p2 = Promise.resolve(p);
console.log(p === p2);   // true

如果向Promise.resolve()通报一个非Promise的thenable值,那末就会睁开这个值,并且在睁开历程会延续到提掏出一个详细的Promise终究值

人人应当会有一点迷惑,thenable是什么,这段话是什么意义

var obj = {
  then(resolve, reject) {
    resolve(42);
  }
};
Promise.resolve(obj).then((msg) => {
  console.log(msg);  //42
});

好了,Promise.resolve()特征讲完了,then返回值同理

同理完了今后呢,就会涌现一些比较有意义的用法

起首就是链式挪用,比如说

var p = Promise.resolve( 21 );
var p2 = p.then( function(v){
  console.log( v ); // 21
  // 用值42添补p2
  return v * 2;
} );
// 衔接p2
p2.then( function(v){
  console.log( v ); // 42
} );

很简单吧,就不赘述了。

另有一个比较有意义,就是Promise完成同步实行,也就是前一个then如果是异步的话,它必需操纵完成后,才会实行背面的then,罕见的写法是如许的

new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('exec in promise it');
    resolve();
  }, 1000);
}).then(() => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('exec in then it');
      resolve();
    }, 1000);
  });
});

这个先过一秒输出第一句话,再过一秒输出第二句话

这个的道理现实上方才Promise.resolve()的第二条,如果返回的是Promise,那末会直接返回这个Promise,在这里,直接返回return的这个Promise后,就会守候这个Promise决定,在一秒后决定完,就实行背面的then

末了一个有关then的学问点了:

一个Promise决定后,这个Promise上一切的经由历程then()注册的回调都邑鄙人一个异步时候节点上顺次被马上挪用,这些回掉中恣意一个都没法影响或许耽搁对其他回调的挪用

var p = new Promise((resolve, reject) => {
  resolve();
});
p.then( function(){
  p.then( function(){
    console.log( "C" );
  } );
  console.log( "A" );
} );
p.then( function(){
  console.log( "B" );
} );
// a b c

这个的重点现实上是这些决定回调都被到场到了一个行列中,输出的递次恰好现实上就代表了他们到场行列后的先后递次

参考书本《你不知道的Javascript中卷》

    原文作者:小辞
    原文地址: https://segmentfault.com/a/1190000017506145
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞