Promise的介绍

异步处理方案
回调处理未来值

function add(getX, getY, cb) {
    var x, y;
    getX(function (xVal) {
      console.log('xxxxxxxx',x,y,xVal)
      x = xVal;
      // 两个都准备好了?
      if (y != undefined) {
        cb(x + y); // 发送和
      }
    });
    getY(function (yVal) {
      console.log('yyyyyyyyyyyyy',x,y,yVal)
      y = yVal;
      // 两个都准备好了?
      if (x != undefined) {
        cb(x + y); // 发送和
      }
    });
}
// fetchX() 和fetchY()是同步或者异步函数
function fetchX(fn) {
    console.log(1000, 'minit')
    fn(1000)
}
function fetchY(fn) {
    setTimeout(() => {
        console.log(2000, 'minitiiiiiiii')
        fn(2000)
    }, 3000)
}

add(fetchX, fetchY, function (sum) {
    console.log(sum); // 是不是很容易?
});
// 1000 minit
// xxxxxxxx undefined undefined 1000
// 2000 minitiiiiiiii
// yyyyyyyyyyyyy 1000 undefined 2000
3000

Promise处理未来值

function fetchX() {
    return new Promise((res,rej)=>{
        res(1000)
    })
}
function fetchY() {
    return new Promise((res,rej)=>{
        setTimeout(() => {
            console.log(2000, 'minityyyyyy')
            res(2000)
        }, 2000)
    })
}
function add(xPromise, yPromise) {
    // Promise.all([ .. ])接受一个promise数组并返回一个新的promise,
    // 这个新promise等待数组中的所有promise完成
    return Promise.all([xPromise, yPromise])
        // 这个promise决议之后,我们取得收到的X和Y值并加在一起
        .then(function (values) {
        // values是来自于之前决议的promisei的消息数组
         return values[0]+values[1];
        });
}
// fetchX()和fetchY()返回相应值的promise,可能已经就绪,
// 也可能以后就绪
add(fetchX(), fetchY())
// 我们得到一个这两个数组的和的promise
// 现在链式调用 then(..)来等待返回promise的决议
.then(function success(sum) {
    console.log(sum); // 这更简单!
},function error(sum) {
    console.log("异常"); // 这更简单!
}); 
// 2000 minityyyyyy
// 3000

如果Promise本身决议时间很长,可以使用超时机制提示失败

// 用于超时一个Promise的工具
function timeoutPromise(delay) {
    return new Promise( function(resolve,reject){
        setTimeout( function(){
            reject( "timeoutPromise Timeout!" );
        }, delay );
    });
}
function foo(){
    return new Promise( function(resolve,reject){
        setTimeout( function(){
            resolve( "foo ok!" );
        }, 4000 );
    });
}
// 设置foo()超时
Promise.race([
    foo(), // 试着开始foo()
    timeoutPromise( 3000 ) // 给它3秒钟
    ]).then(function(value){
        // foo(..)及时完成
        console.log(value)
    },
    function(err){
        // 或者foo()被拒绝,或者只是没能按时完成
        // 查看err来了解是哪种情况
        console.log(err)
    }
);
// timeoutPromise Timeout!

Promise 的定义方式使得它只能被决议一次。如果出于某种原因. Promise 创建代码试图调用resolve(…) 或 reject(…) 多次,或者试图两者都调用,那么这个 Promise 将只会接受第一次决议,并默默地忽略任何后续调用。由于 Promise 只能被决议一次,所以任何通过 then(…) 注册的(每个)回调就只会被调用一次。
当然,如果你把同一个回调注册了不止一次(比如 p.then(f); p.then(f);),那它被调用的次数就会和注册次数相同。
如果使用多个参数调用 resovle(…) 或者 reject(…),第一个参数之后的所有参数都会被默默忽略。

错误和异常
promise定义时出现异常

var p = new Promise( function(resolve,reject){
    foo.bar(); // foo未定义,所以会出错!
    resolve( 42 ); // 永远不会到达这里 :(    
});
p.then(function fulfilled(succ){
    // 永远不会到达这里 :(
        console.log("成功")
    },
    function rejected(err){
        // err将会是一个TypeError异常对象来自foo.bar()这一行
        console.log("错误")
    }
);
// 错误

foo.bar() 中发生的 JavaScript 异常导致了 Promise 拒绝,你可以捕捉并对其作出响应

then中出现异常

var p = new Promise( function(resolve,reject){
    resolve( 42 ); 
});
p.then(function fulfilled(succ){
        foo.bar(); // foo未定义,所以会出错!
        console.log(succ)  // 永远不会到这里
    },
    function rejected(err){
        console.log(err)  // 永远不会到这里
    }
);
//UnhandledPromiseRejectionWarning: ReferenceError: foo is not defined

Promise 链的一个最佳实践就是最后总以一个 catch(…) 结束。我们没有为 then(…) 传入拒绝处理函数,所以默认的处理函数被替换掉了,而这仅仅是把错误传递给了链中的下一个 promise。因此,进入 p 的错误以及 p 之后进入其决议(就像 msg.toLowerCase())的错误都会传递到最后的 handleErrors(…)

var p = Promise.resolve( 42 );
p.then(
    function fulfilled(msg){
        // 数字没有string函数,所以会抛出错误
        console.log( msg.toLowerCase() );
    }
).catch(function(){
    console.log("异常")
});

p.then(…) 调用本身返回了另外一个 promise,正是这个 promise 将会因 TypeError 异常而被拒绝

如果向 Promise.resolve(…) 传递一个非 Promise、非 thenable 的立即值,就会得到一个用这个值填充的 promise。下面这种情况下, promise p1 和 promise p2 的行为是完全一样的:

var p1 = new Promise( function(resolve,reject){
    resolve( 42 );
});
var p2 = Promise.resolve( 42 );
console.log(p1);   // Promise { 42 }
console.log(p2);   // Promise { 42 }

而如果向 Promise.resolve(…) 传递一个真正的 Promise,就只会返回同一个 promise:

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

Promise.resolve(…) 可以接受任何 thenable,将其解封为它的非 thenable 值。从 Promise.resolve(…) 得到的是一个真正的 Promise,是一个可以信任的值。如果你传入的已经是真正的 Promise,那么你得到的就是它本身,所以通过 Promise.resolve(…) 过滤来获得可信任性完全没有坏处。

var p = {
    then: function(cb,errcb) {
        cb( 42 );
        errcb( "evil laugh" );
    }
};
Promise.resolve( p ).then(
    function fulfilled(val){
        console.log( val ); // 42
    },
    function rejected(err){
        // 啊,不应该运行!
        console.log( err ); // 邪恶的笑
    }
);
// 42

每次你对 Promise 调用 then(…),它都会创建并返回一个新的 Promise,我们可以将其链接起来;

var p = Promise.resolve( 21 );
p.then( function(v){
    console.log( v ); // 21
    // 用值42完成连接的promise
    return v * 2;
}).then( function(v){
    console.log( v ); // 42
});

当传递给 Promise.resolve(…) 的 是 一 个 Promise 或 thenable 而 不 是 最 终 值 时 的 运 作 方 式。 Promise.resolve(…) 会直接返回接收到的真正 Promise,或展开接收到的 thenable 值,并在持续展
开 thenable 的同时递归地前进。
从完成(或拒绝)处理函数返回 thenable 或者 Promise 的时候也会发生同样的展开

var p = Promise.resolve( 21 );
p.then( function(v){
    console.log( v ); // 21
    // 创建一个promise并将其返回
    return new Promise( function(resolve,reject){
        // 用值42填充
        resolve( v * 2 );
    });
}).then( function(v){
    console.log( v ); // 42
});

调用 Promise 的 then(…) 会自动创建一个新的 Promise 从调用返回。
在完成或拒绝处理函数内部,如果返回一个值或抛出一个异常,新返回的(可链接的)Promise 就相应地决议。
如果完成或拒绝处理函数返回一个 Promise,它将会被展开,这样一来,不管它的决议值是什么,都会成为当前 then(…) 返回的链接 Promise 的决议值

同步的 try…catch 结构。它只能是同步的,无法用于异步代码模式:

function foo() {
    setTimeout( function(){
        baz.bar();
    }, 100 );
}
try {
    foo();
    // 后面从 `baz.bar()` 抛出全局错误
}catch (err) {
    // 永远不会到达这里
    console.log("错误")
}

只有在 baz.bar() 调用会同步地立即成功或失败的情况下,这里的 try…catch 才能工作。如果 baz.bar() 本身有自己的异步完成函数,其中的任何异步错误都将无法捕捉到。

function foo(cb) {
    setTimeout( function(){
        try {
            var x = baz.bar();
            cb( null, x ); // 成功!
        }catch (err) {
            cb( err );
    }}, 100 );
}
foo(function(err,val){
    if (err) {
        console.error( "错误" ); // 错误
    }else {
        console.log( val );
    }
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值