new Promise() ---- 真面目

对于promise相信很多人并不陌生,开发的过程中或多或少的都用到过,今天我们先不谈源码,看下promise的真面目到底是什么?

随便拉一个控制台打印一下,你会看到下面一长串的东西,这就是promise

这是一个构造函数,函数上有all, race, reject, resolve方法。原型上面有catch,then,方法。

 如果你熟悉构造函数,你就能看的明白,函数上面的方法是这样来调用的,Promise.resolve(),原型上的方法是每一个实例都可以调用的,也就是说,new Promise().then().catch()。至于它为什么可以链式调用,应该是原型上的这些返回的是this,也就是每一个实例吧。今日不谈源码,所以这里不做过多的解释。

下面是一个简单的异步任务封装为同步任务的实现。

  function fun1() {
       return new Promise((resolve, reject) => {
           setTimeout(() => {
                resolve('异步任务1')
           }, 2000)
       })
   }
   fun1().then((res)=>{
       console.log(res) // 异步任务1
   })

我们执行了一个异步,2秒后我们会拿到异步返回的结果,接下来我们可以做任何我们想要的操作。相比callback来说,这样看起更简介些。

如果遇到层层嵌套,一直用callbakc就会形成callback地狱。用promise你将会看到更优雅的解决办法。

 function fun1() {
       return new Promise((resolve, reject) => {
           setTimeout(() => {
                resolve('异步任务1')
           })
       })
   }
   function fun2() {
       return new Promise((resolve, reject) => {
           setTimeout(() => {
                resolve('异步任务2')
           })
       })
   }
   function fun3() {
       return new Promise((resolve, reject) => {
           setTimeout(() => {
                resolve('异步任务3')
           })
       })
   }
   fun1().then((res1)=>{
       console.log(res1)
       return fun2()
   }).then((res2) => {
       console.log(res2)
        return fun3()
   }).then((res3) => {
        console.log(res3)
   })

保证了3个任务按照顺序执行。

return的结果不一定是一个promise实例,也可以是直接的数值。

  fun1().then((res1)=>{
       console.log(res1)
       return '1'
   }).then((res2) => {
       console.log(res2)
        return '2'
   }).then((res3) => {
        console.log(res3)
   })

resolve的值是一个promise

function fun1() {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
           resolve(fun2)
      })
  })
}
function fun2() {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
           resolve(fun3)
      })
  })
}
function fun3() {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
           resolve('异步任务3')
      })
  })
}
fun1().then((res1)=>{
  console.log(res1) // 函数 fun2
  
}).then((res2) => {
  console.log(res2) // undefined
}).then((res3) => {
  console.log(res3) // undefined
})

这样看来,Promise不但没有那么繁琐,也很灵活。

catch的使用

function randomNumber(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字太大了');
            }
        }, 2000);
    });
    return p;            
}

randomNumber()
.then(
    function(data){
        console.log('resolved', data);
        console.log(data);
    })
.catch(
    function(reason){
        console.log('rejected', reason);
    });

 或者 

也可以这么写

randomNumber()
.then(
    function(data){
        console.log('resolved', data);
    }
    ,
    function(reason){
        console.log('rejected', reason);
    }
);

效果一样。

有时候,我们会见到这样的写法,Promise.resolve(),或者Promise.reject(),这又是什么意思呢?直接看代码吧。

Promise.reject('请求异常').then((res1) => {
    // 这里没有执行
    console.log(res1)
}, (error) => {
    // 这里执行了
    console.log(error)
})

Promise.reject()方法返回一个带有拒绝原因的Promise对象。

Promise.resolve()

Promise.resolve('请求成功').then((res1) => {
    // 这里执行了
    console.log(res1)
}, (error) => {
    // 这里没有执行
    console.log(error)
})

如果说reslove的是一个promise呢?返回的将是带有结果的promise的本身。主要看打印日志的顺序。

var original = Promise.resolve(33);
var cast = Promise.resolve(original);
cast.then(function(value) {
  console.log('value: ' + value);
});
console.log('original === cast ? ' + (original === cast));

返回一个带有then方法的对象,下面是MDN上面的例子,很好理解。

// Resolve一个thenable对象
var p1 = Promise.resolve({ 
  then: function(onFulfill, onReject) { onFulfill("fulfilled!"); }
});
console.log(p1 instanceof Promise) // true, 这是一个Promise对象

p1.then(function(v) {
    console.log(v); // 输出"fulfilled!"
  }, function(e) {
    // 不会被调用
});

// Thenable在callback之前抛出异常
// Promise rejects
var thenable = { then: function(resolve) {
  throw new TypeError("Throwing");
  resolve("Resolving");
}};

var p2 = Promise.resolve(thenable);
p2.then(function(v) {
  // 不会被调用
}, function(e) {
  console.log(e); // TypeError: Throwing
});

// Thenable在callback之后抛出异常
// Promise resolves
var thenable = { then: function(resolve) {
  resolve("Resolving");
  throw new TypeError("Throwing");
}};

var p3 = Promise.resolve(thenable);
p3.then(function(v) {
  console.log(v); // 输出"Resolving"
}, function(e) {
  // 不会被调用
});

Promise.all()。

先来看下MDN上对这个方法的解释吧:

Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中  promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。

此实例在 iterable 参数内所有的 promise 都“完成(resolved):

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error)
});

”或参数中不包含 promise :

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error)
});
Promise.all([1, 2, 3]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error)
});

 

如果参数中包含非 promise 值,这些值将被忽略,但仍然会被放在返回数组中(如果 promise 完成的话)

参数中  promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果:

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(reject, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error) // foo
}); 

整个实例失败。Promise.all()会快速返回失败。

注意一下非 promise 值打印顺序,很奇怪,下面的promise怎么先执行了呢?会不会是当传递的参数不是promise的时候,就变成同步了呢?

我们来验证一下:

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error)
});
Promise.all([1, 2, 3]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error)
});
Promise.all([]).then(function(values) {
  console.log(values);
}).catch((error) => {
  console.log(error)
});

好像跟我们想的又不太一样,如果说参数中都是非promise的值,会变成同步任务的话,那么应该说先打印[1,2,3]后打印[]。结果却是相反的,这到底是怎么一回事呢?

var p = Promise.all([1, 2, 3]);
console.log(p)
setTimeout(() => {
    console.log(p)
}, 2000)

这里注意,立即打印p还么有出结果,说明p是异步的,2秒后打印的p结果已经出来了。 


var p1 = Promise.all([]);
console.log(p1)
setTimeout(() => {
    console.log(p1)
}, 2000

 

这里立即打印p1结果就已经出来了,跟2秒后打印的是一样的,这就说明这里的p1是同步的。 

上面的两组看到有什么不同了吗?

 也就是说,如果参数都是非promise,那么仅当,参数是空数组([])的时候,才会变成同步的。

Promise.race()

race 函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。

这个方法平时我们很少遇到,但是确实一个有很用的方法。话不多说,直接看代码吧。

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "later"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "fast"); 
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value); // "fast"
  // 两个都完成,但 p2 更快
});

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "later"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 100, "fast"); 
});

Promise.race([p1, p2]).then(function(value) {
    // 这里没有走
  console.log('resolve', value);
}).catch((error) => {
    console.log('reject', error);
});

 

如果传的迭代是空的,则返回的 promise 将永远等待。

var p = Promise.race([]).then(function(value) {
    // 这里没有走
  console.log('resolve', value);
}).catch((error) => {
    console.log('reject', error);
});

setTimeout(() => {
    console.log(p)
}, 2000)

 一直等待中。

如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。

Promise.race([Promise.resolve(33), Promise.resolve(44)]).then(function(value) {
  console.log('resolve', value);
}).catch((error) => {
    console.log('reject', error);
});

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Redux Promise是一个Redux中间件,它的作用是派发一个Promise对象,并且可以通过参数resolve来触发一个action。通过创建一个Promise实例,我们可以在resolve中定义想要派发的action的类型和payload。这样做的好处是可以更方便地处理异步逻辑,例如在异步请求返回后再派发相应的action来更新状态。 如果你想在你的Redux应用中使用Redux Promise中间件,可以通过npm安装@tracktl/redux-promise-middleware包,或者在你的项目中添加@tracktl/redux-promise-middleware作为依赖。然后你可以在Redux的store中使用applyMiddleware来将Redux Promise中间件添加到中间件链中。 在众多Redux中间件中,处理Redux异步事件的中间件占据了重要的地位。从简单的redux-thunk到redux-promise再到redux-saga等等,它们都提供了各自的解决方案来管理Redux异步流。对于redux-promise来说,它通过Promise对象的特性,让我们可以更加简洁地处理异步逻辑,并且将派发action的过程与异步操作分离开来。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [眼花缭乱的redux中间件,也不过如此](https://blog.csdn.net/dear_mRZhou_/article/details/118529380)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [redux-promise-middleware:声明式Redux Prom中间件](https://download.csdn.net/download/weixin_42137032/16719421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Redux中间件(redux-thunk、redux-promise、redux-saga)](https://blog.csdn.net/yrqlyq/article/details/119243072)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值