Sự khác biệt giữa Lời hứa và Có thể quan sát là gì?

1498
Rohit 2016-05-22 05:43.

Sự khác biệt giữa PromiseObservabletrong Angular là gì?

Ví dụ về mỗi trường hợp sẽ hữu ích trong việc hiểu cả hai trường hợp. Chúng ta có thể sử dụng trong từng trường hợp nào?

28 answers

1658
Günter Zöchbauer 2016-05-22 07:19.

Lời hứa

A Promisexử lý một sự kiện duy nhất khi hoạt động không đồng bộ hoàn thành hoặc không thành công.

Lưu ý: Có những Promisethư viện hỗ trợ hủy bỏ, nhưng ES6 Promisethì không.

Có thể quan sát được

An Observablegiống như một Stream(trong nhiều ngôn ngữ) và cho phép truyền không hoặc nhiều sự kiện trong đó lệnh gọi lại được gọi cho mỗi sự kiện.

Thường Observableđược ưa thích hơn Promisevì nó cung cấp các tính năng của Promisevà hơn thế nữa. Với Observablenó, không thành vấn đề nếu bạn muốn xử lý 0, 1 hay nhiều sự kiện. Bạn có thể sử dụng cùng một API trong mỗi trường hợp.

Observablecũng có lợi thế hơn Promiselà có thể hủy bỏ . Nếu kết quả của một yêu cầu HTTP đến một máy chủ hoặc một số hoạt động async đắt khác là không cần thiết nữa, các Subscriptioncủa một Observablephép hủy đăng ký, trong khi một Promisecuối cùng sẽ gọi sự thành công hay thất bại callback ngay cả khi bạn không cần thông báo hoặc kết quả nó cung cấp nữa.

Trong khi một Promisebắt đầu ngay lập tức, một Observablechỉ bắt đầu nếu bạn đăng ký. Đây là lý do tại sao các Observables được gọi là lười biếng.

Quan sát được cung cấp nhà khai thác như map, forEach, reduce, ... tương tự như một mảng

Ngoài ra còn có các toán tử mạnh như retry(), hoặc replay(), ... thường khá tiện dụng. Danh sách các toán tử được vận chuyển với rxjs

Thực thi lười biếng cho phép xây dựng một chuỗi các toán tử trước khi các toán tử có thể quan sát được thực thi bằng cách đăng ký, để thực hiện một kiểu lập trình khai báo hơn.

355
trungk18 2016-10-20 05:17.

Cả hai PromisesObservablescung cấp cho chúng tôi những thông tin trừu tượng giúp chúng tôi đối phó với bản chất không đồng bộ của các ứng dụng của chúng tôi. Sự khác biệt giữa chúng đã được chỉ ra rõ ràng bởi @ Günter và @Relu.

Vì một đoạn mã có giá trị một nghìn từ, hãy xem qua ví dụ dưới đây để hiểu chúng dễ dàng hơn.

Cảm ơn @Christoph Burgdorf về bài viết tuyệt vời


Angular sử dụng Rx.js Observables thay vì các hứa hẹn để xử lý HTTP.

Giả sử rằng bạn đang xây dựng một chức năng tìm kiếm sẽ hiển thị ngay kết quả khi bạn nhập. Nghe có vẻ quen thuộc nhưng có rất nhiều thử thách đi kèm với nhiệm vụ đó.

  • Chúng tôi không muốn nhấn vào điểm cuối của máy chủ mỗi khi người dùng nhấn một phím, nó sẽ khiến họ ngập trong một cơn bão HTTPyêu cầu. Về cơ bản, chúng tôi chỉ muốn nhấn nó khi người dùng đã ngừng nhập thay vì mọi lần nhấn phím.
  • Đừng nhấn điểm cuối tìm kiếm với cùng một tham số truy vấn cho các yêu cầu tiếp theo.
  • Đối phó với các phản hồi không theo thứ tự. Khi chúng tôi có nhiều yêu cầu trên chuyến bay cùng một lúc, chúng tôi phải tính đến trường hợp chúng quay trở lại theo thứ tự đột xuất. Hãy tưởng tượng lần đầu tiên chúng ta gõ máy tính , dừng lại, một yêu cầu xuất hiện, chúng ta gõ ô tô , dừng lại, một yêu cầu được đưa ra. Bây giờ chúng tôi có hai yêu cầu trong chuyến bay. Rất tiếc, yêu cầu mang kết quả cho máy tính sẽ quay trở lại sau yêu cầu mang kết quả cho ô tô .

Bản demo sẽ chỉ bao gồm hai tệp: app.tswikipedia-service.ts. Tuy nhiên, trong một kịch bản thế giới thực, rất có thể chúng tôi sẽ chia nhỏ mọi thứ ra.


Dưới đây là triển khai dựa trên Lời hứa không xử lý bất kỳ trường hợp cạnh nào được mô tả.

wikipedia-service.ts

import { Injectable } from '@angular/core';
import { URLSearchParams, Jsonp } from '@angular/http';

@Injectable()
export class WikipediaService {
  constructor(private jsonp: Jsonp) {}

  search (term: string) {
    var search = new URLSearchParams()
    search.set('action', 'opensearch');
    search.set('search', term);
    search.set('format', 'json');
    return this.jsonp
                .get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search })
                .toPromise()
                .then((response) => response.json()[1]);
  }
}

Chúng tôi đang đưa Jsonpdịch vụ vào để đưa ra GETyêu cầu đối với API Wikipedia với một cụm từ tìm kiếm nhất định. Lưu ý rằng chúng tôi gọi toPromiseđể đi từ an Observable<Response>đến a Promise<Response>. Cuối cùng kết thúc bằng a Promise<Array<string>>là kiểu trả về của phương pháp tìm kiếm của chúng tôi.

app.ts

// check the plnkr for the full list of imports
import {...} from '...';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Wikipedia Search</h2>
      <input #term type="text" (keyup)="search(term.value)">
      <ul>
        <li *ngFor="let item of items">{{item}}</li>
      </ul>
    </div>
  `
})
export class AppComponent {
  items: Array<string>;

  constructor(private wikipediaService: WikipediaService) {}

  search(term) {
    this.wikipediaService.search(term)
                         .then(items => this.items = items);
  }
}

Không có nhiều bất ngờ ở đây. Chúng tôi đưa vào WikipediaServicevà hiển thị chức năng của nó thông qua một phương pháp tìm kiếm cho mẫu. Mẫu đơn giản liên kết với keyup và cuộc gọi search(term.value).

Chúng tôi mở kết quả của Lời hứa rằng phương thức tìm kiếm của WikipediaService trả về và hiển thị nó dưới dạng một Mảng chuỗi đơn giản cho mẫu để chúng tôi có thể *ngForlặp lại nó và tạo danh sách cho chúng tôi.

Xem ví dụ về triển khai dựa trên Lời hứa trên Plunker


Nơi Người quan sát thực sự tỏa sáng

Hãy thay đổi mã của chúng tôi để không sử dụng điểm cuối với mỗi lần nhấn phím mà thay vào đó chỉ gửi yêu cầu khi người dùng ngừng nhập trong 400 mili giây

Để tiết lộ những siêu năng lực như vậy, trước tiên chúng ta cần lấy một hàm Observable<string>mang cụm từ tìm kiếm mà người dùng nhập vào. Thay vì liên kết thủ công với sự kiện keyup, chúng ta có thể tận dụng formControlchỉ thị của Angular . Để sử dụng chỉ thị này, trước tiên chúng ta cần nhập ReactiveFormsModulevào mô-đun ứng dụng của mình.

app.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { JsonpModule } from '@angular/http';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [BrowserModule, JsonpModule, ReactiveFormsModule]
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

Sau khi được nhập, chúng ta có thể sử dụng formControl từ bên trong mẫu của mình và đặt nó thành tên "term".

<input type="text" [formControl]="term"/>

Trong thành phần của chúng tôi, chúng tôi tạo một thể hiện của FormControlfrom @angular/formvà hiển thị nó dưới dạng một trường dưới thuật ngữ tên trên thành phần của chúng tôi.

Đằng sau hậu trường, thuật ngữ tự động tiết lộ một thuộc Observable<string>tính valueChangesmà chúng tôi có thể đăng ký. Bây giờ chúng tôi có một Observable<string>, việc vượt qua đầu vào của người dùng dễ dàng như việc gọi điện debounceTime(400)của chúng tôi Observable. Điều này sẽ trả về một Observable<string>giá trị mới sẽ chỉ phát ra một giá trị mới khi không có giá trị mới nào đến trong 400ms.

export class App {
  items: Array<string>;
  term = new FormControl();
  constructor(private wikipediaService: WikipediaService) {
    this.term.valueChanges
              .debounceTime(400)        // wait for 400ms pause in events
              .distinctUntilChanged()   // ignore if next search term is same as previous
              .subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));
  }
}

Sẽ rất lãng phí tài nguyên nếu gửi một yêu cầu khác cho một cụm từ tìm kiếm mà ứng dụng của chúng tôi đã hiển thị kết quả. Tất cả những gì chúng tôi phải làm để đạt được hành vi mong muốn là gọi cho tổng đài distinctUntilChangedngay sau khi chúng tôi gọidebounceTime(400)

Xem ví dụ về triển khai có thể quan sát trên Plunker

Để đối phó với các phản hồi không theo thứ tự, vui lòng kiểm tra toàn bộ bài viết http://blog.thoughtram.io/angular/2016/01/06/aking-osystem-of-observables-in-angular2.html

Theo như tôi đang sử dụng Http trong Angular, tôi đồng ý rằng trong các trường hợp sử dụng thông thường, không có nhiều sự khác biệt khi sử dụng Observable thay vì Promise. Không có lợi thế nào thực sự phù hợp ở đây trong thực tế. Hy vọng tôi có thể thấy một số trường hợp sử dụng nâng cao trong tương lai :)


Tìm hiểu thêm

257
Alireza 2017-05-07 20:56.

Cả PromiseObservables sẽ giúp chúng ta làm việc với các chức năng không đồng bộ trong JavaScript. Chúng rất giống nhau trong nhiều trường hợp, tuy nhiên, vẫn có một số khác biệt giữa cả hai, các lời hứa là các giá trị sẽ giải quyết theo các asynchronouscách như lệnh gọi http . Mặt khác, các vật thể quan sát đối phó với một chuỗi các sự kiện không đồng bộ . Sự khác biệt chính giữa chúng được liệt kê dưới đây:

lời hứa:

  • có một đường ống
  • thường chỉ sử dụng với trả về dữ liệu không đồng bộ
  • không dễ dàng để hủy bỏ

có thể quan sát được:

  • có thể hủy bỏ
  • có thể thử lại về bản chất, chẳng hạn như thử lại và thử lại
  • truyền dữ liệu trong nhiều đường ống
  • có các hoạt động giống như mảng như bản đồ, bộ lọc, v.v.
  • có thể được tạo từ các nguồn khác như sự kiện
  • chúng là các chức năng, có thể được đăng ký sau này

Ngoài ra, tôi đã tạo hình ảnh đồ họa cho bạn bên dưới để hiển thị sự khác biệt một cách trực quan:

80
Aravind 2017-01-10 08:29.

Lời hứa

  1. Định nghĩa: Giúp bạn chạy các hàm không đồng bộ và sử dụng các giá trị trả về của chúng (hoặc các ngoại lệ) nhưng chỉ một lần khi được thực thi.
  2. Không lười biếng
  3. Không thể hủy (Có các thư viện Promise hỗ trợ hủy, nhưng ES6 Promise thì không). Hai quyết định có thể là
    • Từ chối
    • Giải quyết
  4. Không thể thử lại (Các lời hứa phải có quyền truy cập vào chức năng ban đầu đã trả lại lời hứa để có khả năng thử lại, đây là một phương pháp không tốt)

Có thể quan sát

  1. Định nghĩa: Giúp bạn chạy các hàm không đồng bộ và sử dụng các giá trị trả về của chúng trong một chuỗi liên tục ( nhiều lần ) khi được thực thi.
  2. Theo mặc định, nó là Lazy vì nó phát ra các giá trị khi thời gian diễn ra.
  3. Có rất nhiều toán tử giúp đơn giản hóa nỗ lực mã hóa.
  4. Một toán tử thử lại có thể được sử dụng để thử lại bất cứ khi nào cần, cũng như nếu chúng ta cần thử lại có thể quan sát được dựa trên một số điều kiện thử lại Khi nào có thể được sử dụng.

    Lưu ý : Danh sách các toán tử cùng với sơ đồ tương tác của họ có sẵn tại RxMarbles.com

78
besserwisser 2017-06-29 10:45.

Có một nhược điểm của Observables bị thiếu trong câu trả lời. Hứa hẹn cho phép sử dụng các hàm async / await của ES7. Với chúng, bạn có thể viết mã không đồng bộ giống như một lệnh gọi hàm đồng bộ, vì vậy bạn không cần gọi lại nữa. Khả năng duy nhất để Observables làm điều này, là chuyển đổi chúng thành Promises. Nhưng khi bạn chuyển đổi chúng thành Promises, bạn chỉ có thể có lại một giá trị trả về:

async function getData(){
    const data = await observable.first().toPromise();
    //do stuff with 'data' (no callback function needed)
}

Đọc thêm: Làm cách nào tôi có thể `chờ đợi 'trên Rx Observable?

42
sudheer nunna 2018-01-18 06:50.

Cả hai Promise và Observables đều chỉ xử lý lệnh gọi không đồng bộ.

Dưới đây là sự khác biệt giữa chúng:

Có thể quan sát được

  1. Phát ra nhiều giá trị trong một khoảng thời gian
  2. Không được gọi cho đến khi chúng tôi đăng ký với Observable
  3. Có thể được hủy bằng cách sử dụng phương thức unsubscribe ()
  4. Cung cấp bản đồ, forEach, lọc, giảm, thử lại và thử lại Khi toán tử

Lời hứa

  1. Chỉ phát ra một giá trị duy nhất tại một thời điểm

  2. Gọi các dịch vụ không có .then và .catch

  3. Không thể bị hủy

  4. Không cung cấp bất kỳ nhà khai thác nào

29
Sajeetharan 2017-10-08 17:43.

Mặc dù câu trả lời này là muộn, tôi đã tóm tắt những điểm khác biệt bên dưới,

Có thể quan sát:

  1. Có thể quan sát chỉ là một functionlấy an observervà trả về function Observer: an object with next, error.
  2. Người quan sát cho phép subscribe/unsubscribedòng dữ liệu của nó, phát ra giá trị tiếp theo cho người quan sát, notifyngười quan sát về errorsvà thông báo cho người quan sát vềstream completion
  3. Observer cung cấp a function to handle next value, lỗi và kết thúc luồng (sự kiện ui, phản hồi http, dữ liệu với ổ cắm web).
  4. Hoạt động multiple valuestheo thời gian
  5. Nó là cancel-able/retry-ablevà hỗ trợ các nhà khai thác như map,filter,reducev.v.
  6. Tạo một Observable có thể - Observable.create()- trả về Observable có thể gọi các phương thức trên - Observer Observable.from()- chuyển đổi một mảng hoặc có thể lặp thành - Observable Observable.fromEvent()- chuyển đổi một sự kiện thành có thể quan sát - Observable.fromPromise()- chuyển Promise thành Observable - Observable.range()- trả về một chuỗi các số nguyên trong phạm vi cụ thể

Lời hứa :

  1. Một lời hứa đại diện cho một nhiệm vụ sẽ hoàn thành trong tương lai;

  2. Những lời hứa trở thành resolved by a value;

  3. Những lời hứa bị từ chối bởi các trường hợp ngoại lệ;

  4. Không cancellablevà nó trở lạia single value

  5. Một lời hứa thể hiện một chức năng (then)

    -sau đó trả về một mới promise;

    -allows cho cái attachmentđó sẽ được thực thi dựa trên state;

    - handlersđược guaranteedthực hiện trong order attached;

24
Marc Pérez 2017-05-13 03:33.

Tôi tin rằng tất cả các câu trả lời khác sẽ giải tỏa những nghi ngờ của bạn. Tuy nhiên, tôi chỉ muốn thêm rằng các vật quan sát được dựa trên lập trình chức năng và tôi thấy rất hữu ích với các chức năng đi kèm với nó như bản đồ, bản đồ phẳng, giảm, nén. Tính nhất quán mà web đạt được, đặc biệt khi nó phụ thuộc vào các yêu cầu API là một cải tiến tàn bạo.

Tôi thực sự khuyên bạn nên sử dụng tài liệu này , vì đó là tài liệu chính thức của ReativeX và tôi thấy nó là tài liệu rõ ràng nhất.

Nếu bạn muốn tìm hiểu về vật có thể quan sát, tôi sẽ đề xuất bài đăng gồm 3 phần này: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

Mặc dù nó dành cho RxJava, nhưng các khái niệm đều giống nhau và nó thực sự được giải thích rõ ràng. Trong tài liệu reactX, bạn có các hàm tương đương cho mỗi chức năng. Bạn phải tìm RxJS.

23
Stephen R. Smith 2017-04-12 19:25.

Tôi vừa giải quyết một vấn đề trong đó Lời hứa là giải pháp tốt nhất và tôi sẽ chia sẻ nó ở đây cho bất kỳ ai tình cờ gặp câu hỏi này trong trường hợp nó hữu ích (đây chính xác là câu trả lời tôi đã tìm kiếm trước đó):

Trong một dự án Angular2, tôi có một dịch vụ nhận một số tham số và trả về một danh sách giá trị để điền các menu thả xuống trên một biểu mẫu. Khi khởi tạo thành phần biểu mẫu, tôi cần gọi cùng một dịch vụ nhiều lần với các tham số khác nhau để xác định một số menu thả xuống khác nhau, tuy nhiên, nếu tôi chỉ đơn giản xếp hàng tất cả các biến để gọi dịch vụ, chỉ có biến cuối cùng thành công và lỗi còn lại ngoài. Dịch vụ tìm nạp từ cơ sở dữ liệu chỉ có thể xử lý một yêu cầu tại một thời điểm.

Cách duy nhất để điền thành công tất cả các biến menu thả xuống là gọi dịch vụ theo cách ngăn một yêu cầu mới được xử lý cho đến khi yêu cầu cuối cùng được hoàn thành và cơ chế Promise / .then đã giải quyết vấn đề một cách tuyệt vời.

  fetchValueList(listCode): Promise<any> {
      return this.dataSvc.getValueList(listCode, this.stateSvc.currentContext, this.stateSvc.currentLanguageCode)
          .map(response => response.json())
          .toPromise();
  }

  initializeDropDowns() {
      this.fetchValueList('First-Val-List')
          .then(data => {
              this.firstValList = data;
              return this.fetchValueList('Second-Val-List')
          }).then(data => {
              this.secondValList = data;
              return this.fetchValueList('Third-Val-List')
          }).then(data => {
              this.thirdValList = data;
          })  }

Tôi đã định nghĩa các chức năng trong thành phần, và sau đó gọi là initializeDropDown () trong ngOnInit.

Hàm fetchValueList trả về một Promise, do đó, lệnh gọi đầu tiên sẽ chuyển mã listCode đầu tiên và khi Promise phân giải, giá trị trả về nằm trong biến dữ liệu trong khối .then nơi chúng ta có thể gán nó cho biến this.firstValList. Khi hàm đã trả về dữ liệu, chúng tôi biết dịch vụ đã kết thúc và có thể an toàn để gọi lại với Mã danh sách thứ hai, giá trị trả về nằm trong biến dữ liệu trong khối .then tiếp theo và chúng tôi gán nó cho biến this.secondValList.

Chúng ta có thể xâu chuỗi điều này nhiều lần theo yêu cầu để điền tất cả các biến và trên khối mã cuối cùng, chúng ta chỉ cần bỏ qua câu lệnh trả về và khối kết thúc.

Đây là một trường hợp sử dụng rất cụ thể, trong đó chúng ta có một dịch vụ duy nhất cần được gọi nhiều lần khi thành phần khởi tạo và nơi dịch vụ phải hoàn thành tìm nạp và trả về một giá trị trước khi nó có thể được gọi lại, nhưng trong trường hợp này, phương thức Promise / .then là lý tưởng.

21
Iosua Sipos 2017-10-03 23:38.

Lời hứa:

  • Cung cấp một giá trị tương lai duy nhất;
  • Không lười biếng;
  • Không thể hủy bỏ;

Có thể quan sát:

  • Phát ra nhiều giá trị theo thời gian;
  • Lười biếng;
  • Có thể hủy bỏ;
  • Hỗ trợ bản đồ, bộ lọc, rút ​​gọn và các toán tử tương tự

Bạn có thể sử dụng các lời hứa thay vì có thể quan sát được khi gọi HTTP trong Angular nếu muốn.

21
Willem van der Veen 2018-08-12 00:02.

Tổng quat:

  • Cả Promise và Observables đều giúp chúng ta xử lý các hoạt động không đồng bộ. Họ có thể gọi các lệnh gọi lại nhất định khi các hoạt động không đồng bộ này được thực hiện.
  • Một Promise chỉ có thể xử lý một sự kiện, Các có thể quan sát dành cho các luồng sự kiện theo thời gian
  • Không thể hủy lời hứa khi chúng đang chờ xử lý
  • Data Observables phát ra có thể được chuyển đổi bằng cách sử dụng các toán tử

Bạn luôn có thể sử dụng một có thể quan sát để xử lý hành vi không đồng bộ vì một có thể quan sát có tất cả các chức năng mà một lời hứa cung cấp (+ bổ sung). Tuy nhiên, đôi khi chức năng bổ sung này mà Observables cung cấp là không cần thiết. Sau đó, sẽ tốn thêm chi phí để nhập một thư viện để nó sử dụng chúng.

Khi nào sử dụng Promises:

Sử dụng những lời hứa khi bạn có một đơn hoạt động async trong đó bạn muốn để xử lý kết quả. Ví dụ:

var promise = new Promise((resolve, reject) => {
  // do something once, possibly async
  // code inside the Promise constructor callback is getting executed synchronously

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

//after the promise is resolved or rejected we can call .then or .catch method on it

promise.then((val) => console.log(val))      // logs the resolve argument
       .catch((val) => console.log(val));    // logs the reject argument

Vì vậy, một lời hứa thực thi một số mã mà nó giải quyết hoặc từ chối. Nếu một trong hai giải quyết hoặc từ chối được gọi là lời hứa sẽ chuyển từ trạng thái đang chờ xử lý sang trạng thái đã giải quyết hoặc bị từ chối . Khi trạng thái hứa được giải quyết, then()phương thức được gọi. Khi trạng thái lời hứa bị từ chối, catch()phương thức được gọi.

Khi nào sử dụng Observables:

Sử dụng Observables khi có một luồng (dữ liệu) theo thời gian mà bạn cần được xử lý. Luồng là một chuỗi các phần tử dữ liệu đang được cung cấp theo thời gian . Ví dụ về các luồng là:

  1. Các sự kiện của người dùng, ví dụ như sự kiện nhấp chuột hoặc keyup. Người dùng tạo ra các sự kiện (dữ liệu) theo thời gian.
  2. Websockets, sau khi máy khách tạo kết nối WebSocket với máy chủ, nó sẽ đẩy dữ liệu theo thời gian.

Trong bản thân có thể quan sát được chỉ định khi sự kiện tiếp theo xảy ra, khi xảy ra lỗi hoặc khi có thể quan sát được hoàn thành . Sau đó, chúng tôi có thể đăng ký với điều này có thể quan sát, kích hoạt nó và trong đăng ký này, chúng tôi có thể chuyển trong 3 lần gọi lại (không phải lúc nào cũng phải chuyển tất cả). Một lệnh gọi lại sẽ được thực hiện để thành công, một lệnh gọi lại để xảy ra lỗi và một lệnh gọi lại để hoàn thành. Ví dụ:

const observable = Rx.Observable.create(observer => {
  // create a single value and complete
  observer.onNext(1);
  observer.onCompleted();
});

source.subscribe(
  x => console.log('onNext: %s', x),   //  success callback
  e => console.log('onError: %s', e),  //  error callback
  () => console.log('onCompleted')     //  completion callback
 );

// first we log: onNext: 1
//  then we log: onCompleted

Khi tạo một đối tượng có thể quan sát, nó yêu cầu một hàm gọi lại cung cấp một đối tượng quan sát. Trên quan sát này, bạn có thể gọi tới onNext, onCompleted, onError. Sau đó, khi Observable được đăng ký, nó sẽ gọi các lệnh gọi lại tương ứng được chuyển vào đăng ký.

12
Gajender Singh 2018-04-11 21:36.

Lời hứa - Cung cấp một giá trị tương lai duy nhất. Không lười biếng. Không thể hủy. Nó sẽ từ chối hoặc giải quyết.

Có thể quan sát - Cung cấp nhiều giá trị trong tương lai. Lười biếng . Có thể hủy bỏ. Nó cung cấp các phương pháp khác bản đồ trực tiếp, bộ lọc, giảm bớt.

10
ramesh sharma 2019-06-24 02:08.

Hứa hẹn và Tương tự có thể quan sát được đầu tiên

  1. Cả hai đều được sử dụng để xử lý mã không đồng bộ.
  2. Hãy tìm ví dụ về lời hứa. Hàm tạo Promise truyền một hàm tham chiếu giải quyết sẽ được gọi khi nó được gọi với một số giá trị sau khi hoàn thành một số tác vụ không đồng bộ.

const promise = new Promise(resolve => {
  setTimeout(() => {
    resolve("Hello from a Promise!");
  }, 2000);
});

promise.then(value => console.log(value));

  1. Ví dụ có thể quan sát ngay bây giờ. Ở đây, chúng tôi cũng chuyển một hàm cho quan sát được, một bộ quan sát để xử lý tác vụ không đồng bộ. Không giống như giải quyết trong lời hứa, nó có phương thức sau và đăng ký thay cho sau đó.

  2. Vì vậy, cả hai đều xử lý các tác vụ không đồng bộ. Bây giờ chúng ta hãy xem sự khác biệt.


const observable = new Observable(observer => {
  setTimeout(() => {
    observer.next('Hello from a Observable!');
  }, 2000);
});

observable.subscribe(value => console.log(value));

Hứa hẹn so với sự khác biệt có thể quan sát được

Lời hứa

  1. Nó giải quyết hoặc từ chối một giá trị duy nhất và có thể xử lý một tác vụ không đồng bộ giá trị duy nhất tại một thời điểm.
  2. Một lời hứa sau khi giải quyết xong giá trị không đồng bộ mà nó hoàn thành, không thể sử dụng được nữa. Chỉ sử dụng một lần và ở đây nó không còn nữa.
  3. Không thể hủy bỏ
  4. Không hỗ trợ rxjs cho các nhà khai thác.

Có thể quan sát được

  1. khả năng phát ra nhiều giá trị không đồng bộ.
  2. Được sử dụng để xử lý luồng sự kiện hoặc giá trị. Hãy xem xét bạn có một mảng nhiều tác vụ hoặc giá trị và bạn muốn mỗi khi giá trị được chèn vào nó sẽ được xử lý tự động. Bất cứ khi nào bạn đẩy một giá trị vào mảng này, tất cả những người đăng ký của mảng đó sẽ tự động nhận được giá trị mới nhất.
  3. Các bảng quan sát hữu ích để quan sát các thay đổi đầu vào, khoảng thời gian lặp lại, các giá trị quảng bá cho tất cả các thành phần con, thông báo đẩy ổ cắm web, v.v.
  4. Có thể được hủy bằng phương pháp hủy đăng ký bất cứ lúc nào.
  5. Một phần tốt nữa hứa hẹn đó là hỗ trợ cho các toán tử rxjs. Bạn có nhiều toán tử đường ống chủ yếu là ánh xạ, bộ lọc, switchMap, kết hợp, v.v. để chuyển đổi dữ liệu quan sát được trước khi đăng ký.


10
Yogesh Waghmare 2019-12-30 21:32.

Promise phát ra một giá trị duy nhất trong khi Observable phát ra nhiều giá trị. Vì vậy, trong khi xử lý một yêu cầu HTTP, Promise có thể quản lý một phản hồi duy nhất cho cùng một yêu cầu, nhưng nếu có nhiều phản hồi cho cùng một yêu cầu thì chúng ta phải sử dụng Observable. Có, Observable có thể xử lý nhiều phản hồi cho cùng một yêu cầu.

Lời hứa

const promise = new Promise((data) =>
{ data(1);
  data(2);
  data(3); })
.then(element => console.log(‘Promise ‘ + element));

Đầu ra

Promise 1

Có thể quan sát được

const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));

Đầu ra

Observable 1
Observable 2
Observable 3
8
DeC 2019-10-29 02:04.

Lời hứa tạo ra một sự kiện khi một hoạt động không đồng bộ kết thúc hoặc không thành công.

Một Observable giống như một Luồng (bằng nhiều ngôn ngữ) và cho phép truyền ít nhất không hoặc nhiều sự kiện trong đó yêu cầu gọi lại cho mọi sự kiện.

Thường xuyên quan sát được ưu tiên hơn Promise vì nó cung cấp các điểm nổi bật của Promise và hơn thế nữa. Với Observable, không thành vấn đề nếu bạn cần xử lý 0, 1 hoặc các sự kiện khác nhau. Bạn có thể sử dụng API tương tự cho từng trường hợp.

Lời hứa: lời hứa tạo ra một giá trị duy nhất

Ví dụ:

const numberPromise = new Promise((resolve) => {
    resolve(5);
    resolve(10);
});

numberPromise.then(value => console.log(value));
// still prints only 5

Có thể quan sát: Phát ra nhiều giá trị trong một khoảng thời gian

Ví dụ:

  const numberObservable = new Observable((observer) => {
        observer.next(5);
        observer.next(10);
    });

numberObservable.subscribe(value => console.log(value));
// prints 5 and 10

chúng ta có thể nghĩ về một luồng có thể quan sát được giống như một luồng phát ra nhiều giá trị trong một khoảng thời gian và cùng một hàm gọi lại được gọi cho mỗi mục được phát ra, vì vậy với một có thể quan sát, chúng ta có thể sử dụng cùng một API để xử lý dữ liệu không đồng bộ. cho dù dữ liệu đó được truyền dưới dạng một giá trị hay nhiều giá trị trong một khoảng thời gian nào đó.

Lời hứa:

  • Một lời hứa không phải là lười biếng
  • Một lời hứa không thể bị hủy bỏ

Có thể quan sát:

  • Có thể quan sát được là Lười biếng. "Có thể quan sát" là chậm. Nó không được gọi cho đến khi chúng tôi đăng ký nó.
  • Một Observable có thể bị hủy bằng cách sử dụng phương thức unsubscribe ()
  • Một bổ sung Observable cung cấp nhiều toán tử mạnh mẽ như bản đồ, foreach, bộ lọc, giảm, thử lại, thử lại

Angular Promise so với Observables

7
Srikrushna 2019-04-30 01:05.

Cả Promise và Observables đều giúp chúng ta xử lý các hoạt động không đồng bộ. Họ có thể gọi các lệnh gọi lại nhất định khi các hoạt động không đồng bộ này được thực hiện.

Angular sử dụng Observables từ RxJS thay vì các hứa hẹn để xử lý HTTP

Below are some important differences in promises & Observables.

4
Amr Ibrahim 2018-10-01 01:57.

Câu trả lời ngắn :

Quan sát đượctốt hơn , nó có tất cả Promises tính năng cộng thêm tính năng bổ sung.


Câu trả lời dài:

Lời hứa:

  • Sử dụng một lần "Trả lại dữ liệu một lần"
  • Không, hủy
  • Một người nghe
  • Không hỗ trợ ổ cắm Một người nghe

Có thể quan sát:

  • Trả lại dữ liệu nhiều lần khi dữ liệu thay đổi
  • Hỗ trợ hủy bỏ
  • Ổ cắm hỗ trợ
  • Hỗ trợ nhiều Listener và thông báo cho họ khi dữ liệu thay đổi
  • Hỗ trợ bản đồ, lọc, giảm
4
Bikram 2018-10-31 11:56.

Dưới đây là một số điểm khác biệt quan trọng trong hứa hẹn & Khả năng quan sát.

Lời hứa

  • Chỉ phát ra một giá trị duy nhất
  • Không thể hủy bỏ
  • Không thể chia sẻ
  • Luôn không đồng bộ

Có thể quan sát được

  • Phát ra nhiều giá trị
  • Chỉ thực thi khi nó được gọi hoặc ai đó đang đăng ký
  • Có thể hủy bỏ
  • Có thể được chia sẻ và đăng ký giá trị được chia sẻ đó bởi nhiều người đăng ký. Và tất cả những người đăng ký sẽ thực hiện tại một thời điểm duy nhất.
  • có thể không đồng bộ

Để hiểu rõ hơn, hãy tham khảo https://stackblitz.com/edit/observable-vs-promises

4
shusson 2018-11-15 03:36.

Mặc dù câu trả lời được chấp nhận nói chung là tốt, tôi không nghĩ rằng nó nhấn mạnh rằng khi xử lý Angular Components, bạn hầu như luôn muốn sử dụng Observable vì nó hỗ trợ hủy. Lời hứa không thể bị hủy bỏ và sẽ giải quyết ngay cả khi thành phần của bạn bị phá hủy. Angular có xu hướng tha thứ cho đến khi nó không.

Ví dụ: bất kỳ phát hiện thay đổi thủ công nào trên một thành phần bị phá hủy sẽ gây ra ngoại lệ:

ngOnInit() {
  // promise api
  this.service.getData().then(d => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });

  // observable api
  this.service.getData().pipe(takeUntil(this.unsubscribe)).subscribe((d) => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });
}

Nếu thành phần của bạn bị hủy trước khi lời hứa được giải quyết, bạn sẽ gặp attempt to use destroyed viewlỗi khi lời hứa được giải quyết.

Ngoài ra, nếu bạn sử dụng các vật có thể quan sát với mẫu Angular / RxJs Khi nào tôi nên hủy đăng ký `` Đăng ký '' , thì ngay sau khi thành phần của bạn bị hủy, đăng ký sẽ bị hủy.

Đây là một chút về ví dụ có sẵn nhưng việc thực thi mã cho một thành phần bị phá hủy có thể dẫn đến lỗi. Trừ khi bạn thực sự muốn làm điều đó vì một lý do nào đó: p

4
Mohideen bin Mohammed 2019-03-08 20:04.

Lời hứa:

Trình xử lý sự kiện không đồng bộ - Đối tượng Promise đại diện cho việc hoàn thành (hoặc thất bại) cuối cùng của một hoạt động không đồng bộ và giá trị kết quả của nó.

Cú pháp: new Promise (người thực thi);

Ví dụ:

var promise_eg = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

promise_eg.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise_eg);

Giới thiệu về Promise: Nó có một đường dẫn, vì vậy nó sẽ trả về các giá trị chỉ một lần khi nó được gọi. trình xử lý một chiều của nó nên một khi được gọi, bạn có thể không hủy được. cú pháp hữu ích mà bạn có thể sử dụng, when ()then ()

Có thể quan sát:

Các quan sát là tập hợp lười biếng của nhiều giá trị theo thời gian. nó thực sự là một cách tiếp cận tuyệt vời cho các hoạt động không đồng bộ. nó có thể được thực hiện với rxjs có hỗ trợ đa nền tảng có thể sử dụng với góc / phản ứng, v.v.

nó hoạt động giống như lót dòng. có thể được nhiều đường ống. vì vậy khi đã xác định, bạn có thể đăng ký để nhận kết quả trả về ở nhiều nơi.

Cú pháp: import * as Rx from "@reactivex/rxjs"; to init:

Rx.Observable.fromEvent(button, "click"),
Rx.Subject()

Vân vân

đăng ký: RxLogger.getInstance();

Ví dụ:

import { range } from 'rxjs';
import { map, filter } from 'rxjs/operators';

range(1, 200).pipe(
  filter(x => x % 2 === 1),
  map(x => x + x)
).subscribe(x => console.log(x));

vì nó hỗ trợ nhiều đường ống dẫn bạn có thể đăng ký ở các vị trí khác nhau, nó có nhiều khả năng hơn so với lời hứa.

Cách sử dụng: nó có nhiều khả năng hơn nhưmap, filter, pipe, map, concatMap etc

3
rpgFANATIC 2019-02-14 12:45.

Điều gì đó mà tôi gặp phải không rõ ràng từ lần đọc đầu tiên của hướng dẫn và tài liệu là ý tưởng về đa hướng.

Đảm bảo rằng bạn biết rằng theo mặc định, nhiều đăng ký sẽ kích hoạt nhiều lần thực thi trong một Có thể quan sát. Nhiều đăng ký cho một cuộc gọi HTTP có thể quan sát được sẽ kích hoạt nhiều lệnh gọi HTTP giống nhau trừ khi bạn .share()(bật đa hướng).

Một lời hứa buộc bạn phải xử lý từng thứ một, mở gói dữ liệu của nó, xử lý các trường hợp ngoại lệ, có hỗ trợ ngôn ngữ cho những thứ thú vị như async / await, và ngược lại là khá dễ hiểu.

Một Observable có rất nhiều chuông và còi, nhưng bạn cần hiểu sức mạnh mà bạn đang làm việc, nếu không nó có thể bị sử dụng sai.

3
Batiste Bieler 2019-03-26 05:01.

Tôi thấy nhiều người sử dụng lập luận rằng Observable là "có thể hủy bỏ" nhưng khá tầm thường khi đặt Promise "có thể hủy"

function cancellablePromise(body) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res; reject = rej;
    body(resolve, reject)
  })
  promise.resolve = resolve;
  promise.reject = reject;
  return promise
}

// Example 1: Reject a promise prematurely
const p1 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('10', 100))
})

p1.then(value => alert(value)).catch(err => console.error(err))
p1.reject(new Error('denied')) // expect an error in the console

// Example: Resolve a promise prematurely
const p2 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('blop'), 100)
})

p2.then(value => alert(value)).catch(err => console.error(err))
p2.resolve(200) // expect an alert with 200

3
ankita kumari 2019-11-04 21:05.

Các khả năng quan sát thường được so sánh với các lời hứa. Dưới đây là một số khác biệt chính:

Các dữ liệu quan sát được khai báo; tính toán không bắt đầu cho đến khi đăng ký. Lời hứa thực hiện ngay lập tức khi tạo. Điều này làm cho khả năng quan sát hữu ích để xác định công thức nấu ăn có thể chạy bất cứ khi nào bạn cần kết quả.

Có thể quan sát cung cấp nhiều giá trị. Lời hứa cung cấp một. Điều này làm cho các giá trị quan sát hữu ích để nhận nhiều giá trị theo thời gian.

Các khả năng quan sát phân biệt giữa chuỗi và đăng ký. Hứa hẹn chỉ có mệnh đề .then (). Điều này làm cho khả năng quan sát hữu ích để tạo ra các công thức biến đổi phức tạp để các bộ phận khác của hệ thống sử dụng mà không làm cho công việc được thực thi.

Observables subscribe () chịu trách nhiệm xử lý lỗi. Lời hứa đẩy lỗi cho đứa trẻ hứa hẹn. Điều này làm cho khả năng quan sát hữu ích cho việc xử lý lỗi tập trung và có thể dự đoán được.

Đó là sự khác biệt đơn giản nhất mà bạn có thể tìm thấy trên tài liệu ANGULAR.IO. phần còn lại câu trả lời được đưa ra bởi hầu hết là đúng ở vị trí của riêng nó

3
Yogesh Waghmare 2019-12-30 21:11.
  1. một Promise là háo hức, trong khi một Observable là lười biếng,
  2. một Lời hứa luôn không đồng bộ, trong khi một Lời hứa có thể đồng bộ hoặc không đồng bộ,
  3. một Lời hứa có thể cung cấp một giá trị duy nhất, trong khi một Lời hứa có thể cung cấp một
    dòng giá trị (từ 0 đến nhiều giá trị),
  4. bạn có thể áp dụng các toán tử RxJS cho một Observable để có một luồng mới phù hợp.
2
Chirag 2019-04-15 22:55.

Sự khác biệt cơ bản giữa lời hứa và có thể quan sát được là:

2
Vignesh 2020-01-02 07:46.
  1. Các hứa hẹn chỉ được tập trung cho các giá trị hoặc độ phân giải đơn lẻ, các phần có thể quan sát được là dòng dữ liệu.

  2. Có thể hủy các vật quan sát được nhưng không thể hủy bỏ lời hứa.

Điều ít được biết đến nhất, với tôi là

  1. Hứa hẹn luôn có bản chất không đồng bộ, nhưng các khả năng quan sát có thể vừa đồng bộ vừa không đồng bộ.
1
Jitendra Dhadavi 2020-06-10 22:07.

Lời hứa

Một Promise xử lý một sự kiện duy nhất khi hoạt động không đồng bộ hoàn thành hoặc không thành công.

Lưu ý: Có thư viện Promise hỗ trợ hủy, nhưng ES6 Promise thì không.

Có thể quan sát được

Một Observable giống như một Luồng (trong nhiều ngôn ngữ) và cho phép chuyển không hoặc nhiều sự kiện trong đó gọi lại được gọi cho mỗi sự kiện.

1
Kamran Khatti 2020-09-30 10:21.

Tóm lại, sự khác biệt chính giữa Lời hứa và Người có thể quan sát như sau:

  • một Promise là háo hức, trong khi một Observable là lười biếng,
  • một Lời hứa luôn không đồng bộ, trong khi một Lời hứa có thể đồng bộ hoặc không đồng bộ,
  • một Lời hứa có thể cung cấp một giá trị duy nhất, trong khi một Lời hứa có thể cung cấp một dòng giá trị (từ 0 đến nhiều giá trị),
  • bạn có thể áp dụng các toán tử RxJS cho một Observable để có một luồng mới phù hợp.

chi tiết hơn có thể được tìm thấy trong bài viết này

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Làm thế nào để xây dựng một quả địa cầu từ Scratch

Làm thế nào để xây dựng một quả địa cầu từ Scratch

Thời gian, sự kiên nhẫn, thời gian, sự cống hiến và thời gian chỉ là một vài trong số những thứ mà Peter Bellerby cần để thành lập và sau đó điều hành Bellerby & Co. Globemakers, một trong những công ty duy nhất trên Trái đất vẫn sản xuất các quả địa cầu bằng tay.

Năm giai đoạn đau buồn sau khi mất việc làm

Năm giai đoạn đau buồn sau khi mất việc làm

Đó là một ngày thứ Bảy, máy bay của tôi hạ cánh, và tôi đã sẵn sàng để thư giãn trong một kỳ nghỉ cuối tuần ngắn ngủi, khi một email đến trên điện thoại của tôi. Tôi đã mất việc.

Giữ an toàn cho danh tính của bạn với một cảnh báo đóng băng hoặc gian lận tín dụng

Giữ an toàn cho danh tính của bạn với một cảnh báo đóng băng hoặc gian lận tín dụng

Nếu bạn đã từng bị đánh cắp danh tính của mình, bạn biết đó là một trải nghiệm đáng sợ và căng thẳng. Một cách không phổ biến để ngăn chặn nó? Tín dụng bị đóng băng.

Buổi ra mắt phần 3 của The Good Place có một học sinh mới: Khán giả

Buổi ra mắt phần 3 của The Good Place có một học sinh mới: Khán giả

Eleanor (Kristen Bell) dường như đã tình nguyện cho chúng tôi làm vật tưởng nhớ. NBC's The Good Place là một chương trình thích thử thách tốt.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language