Promise 是异步编程的一种新解决方案。 ES6已将其纳入语言标准,统一其用法并原生提供Promise对象。
它的引入极大地改善了异步编程的困境,避免了回调地狱。它比回调函数和事件等传统解决方案更合理、更强大。
Promise,简单地说,是一个构造函数,它保存将来将完成的事件(通常是异步操作)的结果。从语法上来说,Promise 是一个可以从中检索异步操作消息的对象。 Promise 提供了统一的 API,允许以相同的方式处理各种异步操作。
可以有效解决ES5中的回调地狱问题(避免回调函数深度嵌套)。
遵循统一标准,语法简洁,可读性强,可维护性强。
Promise 对象提供了简单的 API,让管理异步任务更加方便灵活。
使用 Promise 时,我们可以将其分为三种状态:
待处理:待处理。这是初始状态,Promise 既没有被履行,也没有被拒绝。
已完成:已完成/已解决/成功。当执行resolve()时,Promise立即进入该状态,表示已经解决,任务成功完成。
拒绝:拒绝/失败。当执行reject()时,Promise立即进入该状态,表示已被拒绝,任务失败。
当执行new Promise()时,promise对象的状态被初始化为pending,这是它的初始状态。 new Promise()行括号内的内容是同步执行的。在括号内,您可以为异步任务定义一个函数,该函数有两个参数:resolve 和reject。例如:
// Create a new promise const promise = new Promise((resolve, reject) => { //promise's state is pending as soon as entering the function console.log('Synchronous Operations'); //Begin to execute asynchronous operations if (Success) { console.log('success'); // If successful, execute resolve() to switch the promise's state to Fulfilled resolve(Success); } else { // If failed, excecute reject() to pass the error and switch the state to Rejected reject(Failure); } }); console.log('LukeW'); //Execute promise's then():to manage success and failure situations promise.then( successValue => { // Process promise's fulfilled state console.log(successValue, 'successfully callback'); // The successMsg here is the Success in resolve(Success) }, errorMsg => { //Process promise's rejected state console.log(errorMsg, 'rejected'); // The errorMsg here is the Failure in reject(Failure) } );
Promise 构造函数以一个函数作为参数,该函数有两个参数:resolve 和reject。
const promise = new Promise((resolve, reject) => { // ... some code if (/* Success */){ resolve(value); } else { reject(error); } });
Promise.resolve(value) 的返回值也是一个 Promise 对象,可以与 .then 调用链接起来。代码如下:
Promise.resolve(11).then(function(value){ console.log(value); // print 11 });
在resolve(11)代码中,它将导致promise对象转换到resolved状态,将参数11传递给后续.then中指定的onFulfilled函数。可以使用新的 Promise 语法或使用 Promise.resolve(value) 创建 Promise 对象。
function testPromise(ready) { return new Promise(function(resolve,reject){ if(ready) { resolve("hello world"); }else { reject("No thanks"); } }); }; testPromise(true).then(function(msg){ console.log(msg); },function(error){ console.log(error); });
上面代码的意思是向testPromise方法传递一个参数,该方法返回一个promise对象。如果参数为true,则调用promise对象的resolve()方法,然后将传递给它的参数传递给后续.then中的第一个函数,结果是输出“hello world”。如果参数为 false,则调用 Promise 对象的reject() 方法,这会触发 .then 中的第二个函数,导致输出“NoThanks。”
then 方法可以接受两个回调函数作为参数。第一个回调函数在Promise对象的状态变为resolved时调用,第二个回调函数在Promise对象的状态变为rejected时调用。第二个参数是可选的,可以省略。
then 方法返回一个新的 Promise 实例(不是原始的 Promise 实例)。因此,可以使用链式语法,在第一个方法之后调用另一个 then 方法。
当需要顺序编写异步事件,要求串行执行时,可以这样写:
let promise = new Promise((resolve,reject)=>{ ajax('first').success(function(res){ resolve(res); }) }) promise.then(res=>{ return new Promise((resovle,reject)=>{ ajax('second').success(function(res){ resolve(res) }) }) }).then(res=>{ return new Promise((resovle,reject)=>{ ajax('second').success(function(res){ resolve(res) }) }) }).then(res=>{ })
除了then方法之外,Promise对象还有一个catch方法。该方法相当于then方法的第二个参数,指向reject的回调函数。不过catch方法还有一个额外的功能:如果在执行resolve回调函数时发生错误或者抛出异常,它不会停止执行。而是会进入catch方法。
p.then((data) => { console.log('resolved',data); },(err) => { console.log('rejected',err); } ); p.then((data) => { console.log('resolved',data); }).catch((err) => { console.log('rejected',err); });
The all method can be used to complete parallel tasks. It takes an array as an argument, where each item in the array is a Promise object. When all the Promises in the array have reached the resolved state, the state of the all method will also become resolved. However, if even one of the Promises changes to rejected, the state of the all method will become rejected.
let promise1 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(1); },2000) }); let promise2 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(2); },1000) }); let promise3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(3); },3000) }); Promise.all([promise1,promise2,promise3]).then(res=>{ console.log(res); //result:[1,2,3] })
When the all method is called and successfully resolves, the result passed to the callback function is also an array. This array stores the values from each Promise object when their respective resolve functions were executed, in the order they were passed to the all method.
The race method, like all, accepts an array where each item is a Promise. However, unlike all, when the first Promise in the array completes, race immediately returns the value of that Promise. If the first Promise's state becomes resolved, the race method's state will also become resolved; conversely, if the first Promise becomes rejected, the race method's state will become rejected.
let promise1 = new Promise((resolve,reject)=>{ setTimeout(()=>{ reject(1); },2000) }); let promise2 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(2); },1000) }); let promise3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(3); },3000) }); Promise.race([promise1,promise2,promise3]).then(res=>{ console.log(res); //result:2 },rej=>{ console.log(rej)}; )
So, what is the practical use of the race method? When you want to do something, but if it takes too long, you want to stop it; this method can be used to solve that problem:
Promise.race([promise1,timeOutPromise(5000)]).then(res=>{})
The finally method is used to specify an operation that will be executed regardless of the final state of the Promise object. This method was introduced in the ES2018 standard.
promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});
In the code above, regardless of the final state of the promise, after the then or catch callbacks have been executed, the callback function specified by the finally method will be executed.
In work, you often encounter a requirement like this: for example, after sending an A request using AJAX, you need to pass the obtained data to a B request if the first request is successful; you would need to write the code as follows:
let fs = require('fs') fs.readFile('./a.txt','utf8',function(err,data){ fs.readFile(data,'utf8',function(err,data){ fs.readFile(data,'utf8',function(err,data){ console.log(data) }) }) })
The above code has the following drawbacks:
The latter request depends on the success of the previous request, where the data needs to be passed down, leading to multiple nested AJAX requests, making the code less intuitive.
Even if the two requests don't need to pass parameters between them, the latter request still needs to wait for the success of the former before executing the next step. In this case, you also need to write the code as shown above, which makes the code less intuitive.
After the introduction of Promises, the code becomes like this:
let fs = require('fs') function read(url){ return new Promise((resolve,reject)=>{ fs.readFile(url,'utf8',function(error,data){ error && reject(error) resolve(data) }) }) } read('./a.txt').then(data=>{ return read(data) }).then(data=>{ return read(data) }).then(data=>{ console.log(data) })
This way, the code becomes much more concise, solving the problem of callback hell.
以上是Javascript:Promise 完整指南的详细内容。更多信息请关注PHP中文网其他相关文章!