Promise Javascript Là Gì

Share:

Chời, thời này ai xài Promise nữa. Chuẩn hiện thời là async/await.-- Ai kia bên trên mạng

Hãy khoan chúng ta ơi, đừng cấp khiêu vũ lên chuyến tàu tốc hành async/await trong những khi chưa rành Promise, kẻo lại xảy ra "va chạm Khi dồn dịch", tạo ra kết quả khôn lường, vì chưng căn uống phiên bản async/await vẫn sử dụng Promise nghỉ ngơi bên dưới nhưng mà thôi.

Bạn đang đọc: Promise javascript là gì

diymcwwm.com đã điểm hầu như tư tưởng căn uống phiên bản về Promise, đồng thời so sánh cùng với async/await để thấy khi nào thì nên cần xài mặt hàng như thế nào nhé.

Nhắc lại, Promise là gì?

Promise là một trong cơ chế vào JavaScript khiến cho bạn thực hiện những tác vụ bất đồng điệu mà lại ko lâm vào hoàn cảnh callbaông xã hell xuất xắc pyramid of doom, là triệu chứng những hàm callback lồng vào nhau ở quá nhiều tầng. Các tác vụ bất đồng nhất hoàn toàn có thể là gửi AJAX request, call hàm phía bên trong setTimeout, setInterval hoặc requestAnimationFrame, xuất xắc thao tác làm việc với WebSocket hoặc Worker... Dưới đó là một callbaông xã hell điển hình nổi bật.

api.getUser('pikalong', function(err, user) if (err) throw err api.getPostsOfUser(user, function(err, posts) if (err) throw err api.getCommentsOfPosts(posts, function(err, comments) // vân vân với mây mây... ) ) )ví dụ như bên trên khi được viết lại bằng Promise đã là:

api .getUser('pikalong') .then(user => api.getPostsOfUser(user)) .then(posts => api.getCommentsOfPosts(posts)) .catch(err => throw err )Để tạo ra một promise object thì các bạn sử dụng class Promise có sẵn vào trình lưu ý nlỗi sau:

const p = new Promise( /* executor */ function(resolve, reject) // Thực thi các tác vụ bất đồng bộ ở đây, và gọi `resolve(result)` lúc tác // vụ dứt. Nếu xảy ra lỗi, gọi đến `reject(error)`. , )Trong đó, executor là một trong hàm gồm nhị tđắm đuối số:

resolve sầu là hàm sẽ được call khi promise hoàn thànhreject là hàm sẽ tiến hành gọi khi gồm lỗi xảy ra

Ví dụ:

api.getUser = function(username) // Hàm api.getUser() trả về một promise object return new Promise((resolve sầu, reject) => // Gửi AJAX request http.get(`/users/$username`, (err, result) => // Nếu có lỗi bên trong callbachồng, chúng ta gọi đến hàm `reject()` if (err) return reject(err) // Ngược lại, sử dụng `resolve()` để trả dữ liệu về mang đến `.then()` resolve(result) ) ) vì vậy api.getUser() sẽ trả về một promise object. Chúng ta rất có thể truy nã xuất cho kết quả trả về bằng thủ tục .then() nlỗi sau:

function onSuccess(user) console.log(user) function onError(err) console.error(error) api.getUser('pikalong').then(onSuccess, onError)Phương thơm thức .then(onSuccess, onError) nhấn vào nhị hàm: onSuccess được Gọi khi promise ngừng cùng onError được gọi khi gồm lỗi xảy ra. Bên trong ttê mê số onSuccess bạn cũng có thể trả về một quý giá đồng bộ, ví dụ như quý giá số, chuỗi, null, undefined, array xuất xắc object; hoặc một promise object không giống. Các quý giá bất nhất quán sẽ tiến hành bọc bên phía trong một Promise, có thể chấp nhận được bạn liên kết (chaining) những promises lại cùng nhau.

promise() .then(() => return 'foo' ) .then(result1 => console.log(result1) // 'foo' return anotherPromise() ) .then(result2 => console.log(result2)) // `result2` sẽ là kết quả của anotherPromise() .catch(err => )Trong ví dụ trên, các bạn thấy mang lại cách tiến hành .catch(). Phương thơm thức này chỉ với cú pháp quấn đường (syntactic sugar) của .then(null, onError) mà thôi. Chúng ta sẽ nói thêm về .catch() nghỉ ngơi dưới.

Tạo nhanh hao Promise cùng với Promise.resolve() với Promise.reject()

Có đầy đủ trường vừa lòng chúng ta chỉ cần bọc một quý hiếm vào promise giỏi tự động hóa reject. Thay vì dùng cú pháp new Promise() nhiều năm mẫu, chúng ta có thể cần sử dụng nhì cách thức tĩnh Promise.resolve(result) cùng Promise.reject(err)

const p = Promise.resolve(12) .then(result => console.log(result)) // 12 .then(res => Promise.reject(new Error('Dừng lại nhanh'))) .then(() => 'Cười thêm phát nữa là tym anh đứt phanh') .catch(err => console.error(err)) // Error: Dừng lại nhanh

Còn async/await là cái chi?

Được trình làng vào ES8, async/await là 1 cơ chế giúp bạn tiến hành các thao tác làm việc bất đồng điệu một bí quyết tuần tự hơn. Async/await vẫn áp dụng Promise ở bên dưới tuy vậy mã nguồn của công ty (theo một bí quyết nào đó) đã trong sạch với dễ quan sát và theo dõi.

Để áp dụng, các bạn cần khai báo hàm cùng với trường đoản cú khóa async. Lúc đó bên phía trong hàm chúng ta có thể cần sử dụng await.

async function() try const user = await api.getUser('pikalong') const posts = await api.getPostsOfUser(user) const comments = await api.getCommentsOfPosts(posts) console.log(comments) catch (err) console.log(err) Cần chú ý là tác dụng trả về của async function vẫn là một Promise.

async function hello() return 1 console.log(hello() instanceof Promise) // true hello().then(console.log) // 1Căn bạn dạng về Promise và async/await là vậy. Hiện giờ, bạn đã có thể áp dụng Promise và async/await sinh hoạt toàn bộ những trình chuyên chú hiện đại (trừ IE11 ra nhé, bạn vẫn cần polyfill mang đến nó). Hãy xem phần đông ngôi trường hòa hợp đề nghị xem xét lúc áp dụng bọn chúng.

"Kim trường đoản cú tháp" Promises

Một lỗi chúng ta giỏi phạm phải lúc bắt đầu làm cho quen cùng với Promise, đó là tạo ra "klặng từ tháp" promises như thế này.

api .getUser('pikalong') .then(user => api .getPostsOfUser(user) .then(posts => api .getCommentsOfPosts(posts) .then(comments => console.log(comments) ) .catch(err => console.log(err)) ) .catch(err => console.log(err)) ) .catch(err => console.log(err))Lý vì chưng vị bọn họ xem nhẹ đặc điểm liên kết (chaining) của promise, cho phép phía bên trong hàm resolve rất có thể trả về một quý hiếm đồng nhất hoặc một promise không giống. Do kia cách giải quyết và xử lý là:

api .getUser('pikalong') // Trả về một promise .then(user => api.getPostsOfUser(user)) .then(posts => api.getCommentsOfPosts(posts)) .catch(err => throw err )Theo diymcwwm.com, bài toán đọc cùng thực hiện thuần thục tính link là một trong Một trong những điểm QUAN TRỌNG NHẤT lúc làm việc cùng với Promise. Lúc promise lồng vào với nhau tự 2 tầng trsinh sống lên thì đã tới khi các bạn phải refactor lại rồi.

Luôn gửi vào .then() một hàm

quý khách hàng demo đoán thù coi đoạn code sau vẫn in ra gì?

Promise.resolve(1) .then(2) .then(console.log)Câu vấn đáp là một trong những kia. Pmùi hương thức .then yên cầu tham số của chính nó đề nghị là một trong những hàm. Nếu chúng ta đưa vào .then() một cực hiếm, nó có khả năng sẽ bị bỏ lỡ, lý giải vì sao đoạn code bên trên hiển thị 1. Trường vừa lòng tương tự:

Promise.resolve(1) .then(Promise.resolve(2)) .then(console.log) // 1Cách giải quyết:

Promise.resolve(1) .then(() => 2) // hoặc như thế này, mặc mặc dù hơi dư thừa .then(() => Promise.resolve(2)) .then(console.log) // 2Chúng ta sẽ được kết quả như ý.

Cẩn thận với this khi dùng tsi chiếu hàm

Giả sử bạn có đoạn code sau:

const add2 = x => x + 2 Promise.resolve(4).then(result => add2(result))Hàm onSuccess ko làm cái gi không giống kế bên việc chuyển result vào đến add2, phải chúng ta cũng có thể cần sử dụng ttê mê chiếu hàm nhằm đoạn code bên trên gọn rộng.

Promise.resolve(4).then(add2)Quý Khách rất có thể nghĩ về, vậy với thủ tục của một đối tượng người sử dụng, ta cũng rất có thể đưa tyêu thích chiếu hàm vào .then()?

class User constructor(user) this.user = user getUsername() return this.user.username const u = new User( username: 'pikalong' ) Promise.resolve() .then(u.getUsername) .then(console.log)Nhưng các bạn lại nhận ra lỗi sau:

Unhandled rejection:

Lý vày là vì lúc vào strict mode, trở thành ngữ chình ảnh this chỉ được xác định Khi thẳng Gọi cách thức của đối tượng người sử dụng đó, hoặc trải qua .bind(). quý khách hoàn toàn có thể coi phân tích và lý giải chi tiết hơn ở chỗ này.

Xem thêm: Cách Làm Gà Tiềm Thuốc Bắc Thơm Ngon Bổ Dưỡng Dễ Làm Tại Nhà

Để xử lý lỗi này, chúng ta cũng có thể sử dụng một giữa những bí quyết sau:

.then(() => u.getUsername()) // hoặc .then(u.getUsername.bind(u)) // hoặc cần sử dụng hàm mũi thương hiệu lúc knhì báo phương thức vào class (cần plugin // `transform-class-properties` của Babel) class User // ... getUsername = () => return this.user.username

Chạy các Promise tuần tự

*

Trong ngôi trường thích hợp ước ao chạy những promises một bí quyết tuần từ bỏ nhỏng sơ đồ làm việc bên trên, bạn có thể dùng hàm Array.prototype.reduce .

;.reduce(function(currentPromise, promise) return currentPromise.then(promise) , Promise.resolve()) // Đoạn ở trên khi được viết dài mẫu ra Promise.resolve() .then(promise1) .then(promise2) .then(promise3)Async/await mang lại chiến thuật "xinch đẹp" hơn, được cho phép bạn truy tìm xuất mang đến cực hiếm của các promises vùng trước trường hợp cần thiết.

async function() const res1 = await promise1() const res2 = await promise2(res1) const res3 = await promise3(res2)

Chạy nhiều Promises đồng thời cùng với Promise.all()

Lại gồm ngôi trường vừa lòng bạn muốn xúc tiến với kéo ra công dụng của tương đối nhiều promises đồng thời. Giải pháp "ntạo thơ" đã là sử dụng vòng lặp, hoặc .forEach.

const userIds = <1, 2, 3, 4> // api.getUser() là hàm trả về promise const users = <> for (let id of userIds) api.getUser(id).then(user => <...users, user>) console.log(users) // <>, oát-đờ-heo?Lý do bởi vì Khi promise còn chưa kịp resolve sầu thì dòng console.log đã chạy rồi. Chúng ta có thể sửa bằng phương pháp sử dụng Promise.all(). Pmùi hương thức này thừa nhận vào một trong những mảng các promises còn chỉ resolve sầu khi toàn bộ những promises này hoàn thành, hoặc reject lúc một trong những bọn chúng xảy ra lỗi.

*

const userIds = <1, 2, 3, 4> Promise.all(usersIds.map(api.getUser)).then(function(arrayOfResults) const = arrayOfResults )Nếu sử dụng async/await thì...

async function() const userIds = <1, 2, 3, 4> const = await Promise.all(usersIds.map(api.getUser))

Đừng quên Promise.race()

*

Ngoài nhị đẳng cấp chạy tuần tự và tuy nhiên tuy vậy làm việc bên trên, chúng ta còn có Promise.race(). Pmùi hương thức này nhận vào trong 1 mảng các promises với đang resolve/reject ngay trong lúc một trong các các promises này trả thành/xẩy ra lỗi.

Promise.race(< ping('ns1.example.com'), ping('ns2.example.com'), ping('ns3.example.com'), ping('ns4.example.com'), >).then(result => )

Cẩn thận cùng với return ko tường minh

Xét hai đoạn mã sau:

api .getUser('pikalong') .then(user => return api.getPostsByUser(user) ) .then(console.log) // posts api .getUser('pikalong') .then(user => api.getPostsByUser(user) ) .then(console.log) // undefinedĐoạn mã lắp thêm nhì trả về undefined vì vào JavaScript nếu như một hàm ko công khai trả về một cực hiếm, undefined khoác định sẽ tiến hành trả về (nguồn). Do kia, bạn cần chú ý về giá trị return lúc thao tác cùng với Promise.

Phân biệt .then(resolve, reject) với .then(resolve).catch(reject)

Hàm reject trong .then(resolve, reject) chỉ có thể chụp được lỗi tự mọi .then() vùng phía đằng trước nó, nhưng mà cần yếu bắt được lỗi xẩy ra vào hàm resolve sầu thuộc cung cấp.

api.getUser('pikalong').then( user => throw new Error('Lỗi rồi bạn ei') , err => /* Không bao gồm gì ở đây cả */ , ) api .getUser('pikalong') .then(user => throw new Error('Lỗi rồi bạn ei') ) .catch(err => console.log(err)) // Chụp được rồi bạn eiLưu ý là promise sẽ ngừng quy trình xúc tiến lúc bắt được lỗi

Promise.resolve() .then(() => throw 'foo' ) .then( () => throw 'bar' , err => console.error('here', err) , ) .catch(err => console.error('final', err)) // console: // "here foo"

Truyền dữ liệu giữa những promises với nhau

giữa những điểm giảm bớt của Promise là không có cơ chế mang định nhằm bạn truyền dữ liệu thân những promise objects cùng nhau. Nghĩa là:

api .getUser('pikalong') .then(user => api.getPostsByUser(user)) .then(posts => // Muốn sử dụng biến user ở trên thì làm thế nào đây? )Một biện pháp là dùng Promise.all().

api .getUser('pikalong') .then(user => Promise.all()) .then(results => // Dùng kỹ thuật phân tung biến vào ES6. Bạn lưu ý bọn họ sử dụng 1 dấu , để // bóc tách ra phần tử thứ hai của mảng nhưng mà thôi const <, posts> = results // Lại tiếp tục truyền dữ liệu bao gồm xuống promise sau return Promise.all(<...results, api.getCommentsOfPosts(posts)>) )Hoặc, nếu như bạn cảm thấy phân tách mảng cực nhọc dùng vì chưng buộc phải nhớ máy từ của các giá trị thì ta hoàn toàn có thể sử dụng object như sau:

api .getUser('pikalong') .then(user => api.getPostsByUser(user).then(posts => ( user, posts ))) .then(results => api .getCommentsOfPosts(results.posts) .then(comments => ( ...results, comments )), ) .then(console.log) // users, posts, comments Lại một lần nữa, async/await lại tỏa sáng bởi vì giúp bạn tầm nã xuất cho công dụng của các promises vùng trước.

async function() const user = await api.getUser('pikalong') const posts = await api.getPostsOfUser(user) const comments = await api.getCommentsOfPosts(posts)

Cẩn thận nha, Promise ko lazy

Với đoạn code sau:

console.log('before') const promise = new Promise(function fn(resolve sầu, reject) console.log('hello') // ... ) console.log('after')Kết quả được in ấn ra console thứu tự đã là:

before hello afterBạn có thể thấy hàm executor của Promise được triển khai tức thì chớp nhoáng. Điều này rất có thể dẫn tới những hiệu quả không mong muốn, chẳng hạn như:

const getUsers = new Promise((resolve, reject) => return http.get(`/api`, (err, result) => err ? reject(err) : resolve(result), ) ) button.oncliông xã = e => getUsersCách xử lý là chuyển vào một hàm trả về promise.

const getUsers = () => new Promise((resolve, reject) => return http.get(`/api`, (err, result) => err ? reject(err) : resolve(result), ) ) button.onclichồng = e => getUsers()

Cuối cùng, .finally()

Bên cạnh .then() và .catch(), họ còn tồn tại .finally(onFinally). Phương thơm thức này nhấn vào trong 1 hàm với sẽ được kích hoạt mặc dù rằng promise trước nó dứt hay xẩy ra lỗi.

showLoadingSpinner() api.getUser('pikalong') .then(user => ) .catch(err => ) .finally(hideLoadingSpinner) // async/await async function() try showLoadingSpinner() api.getUser('pikalong') catch(err) finally hideLoadingSpinner() Bạn có thể bài viết liên quan về Promise.prototype.finally() ở đây. Lưu ý là thủ tục này hiện nay chỉ được cung ứng vì chưng Firefox, Chrome và Opera thôi nhé.

Kết

Quý khách hàng rất có thể thấy Promise và async/await ko hoàn toàn sửa chữa thay thế mà lại cung ứng lẫn nhau. Mặc cho dù chúng ta có thể cần sử dụng async/await sinh hoạt phần nhiều các trường hòa hợp, Promise vẫn luôn là nền tảng gốc rễ cần thiết lúc xúc tiến các tác vụ bất đồng điệu vào JavaScript. Do đó bạn nên chăm chú với tuyển lựa chiến thuật phù hợp, tùy vào tình trạng thực tiễn nhá.

Bài viết liên quan