อะไรคือความแตกต่างระหว่างสัญญา JavaScript และ async รอ?


106

ฉันใช้คุณสมบัติECMAScript 6และ ECMAScript 7 อยู่แล้ว (ขอบคุณ Babel) ในแอปพลิเคชันของฉัน - ทั้งมือถือและเว็บ

ขั้นตอนแรกที่เห็นได้ชัดคือ ECMAScript 6 ระดับ ฉันได้เรียนรู้รูปแบบการไม่ซิงค์คำสัญญา (ซึ่งมีแนวโน้มจริงๆ) เครื่องกำเนิดไฟฟ้า (ไม่แน่ใจว่าทำไมจึงต้องใช้สัญลักษณ์ *) ฯลฯ จากสิ่งเหล่านี้สัญญาจึงเหมาะกับจุดประสงค์ของฉัน และฉันได้ใช้มันในแอปพลิเคชันของฉันค่อนข้างมาก

นี่คือตัวอย่าง / รหัสเทียมของวิธีที่ฉันใช้คำสัญญาพื้นฐาน -

var myPromise = new Promise(
    function (resolve,reject) {
      var x = MyDataStore(myObj);
      resolve(x);
    });

myPromise.then(
  function (x) {
    init(x);
});

เมื่อเวลาผ่านไปฉันได้พบกับคุณลักษณะของ ECMAScript 7 และหนึ่งในนั้นคือASYNCและAWAITคำหลัก / ฟังก์ชัน สิ่งเหล่านี้ร่วมกันทำสิ่งมหัศจรรย์ที่ยิ่งใหญ่ async & awaitฉันได้เริ่มต้นที่จะมาแทนที่บางส่วนของสัญญาของฉันด้วย ดูเหมือนจะเพิ่มมูลค่าให้กับรูปแบบการเขียนโปรแกรม

อีกครั้งนี่คือรหัสเทียมของฟังก์ชัน async, await ของฉันว่าเป็นอย่างไร -

async function myAsyncFunction (myObj) {
    var x = new MyDataStore(myObj);
    return await x.init();
}
var returnVal = await myAsyncFunction(obj);

การรักษาข้อผิดพลาดทางไวยากรณ์ (ถ้ามี) ไว้ทั้งคู่ทำสิ่งเดียวกันกับที่ฉันรู้สึก ฉันเกือบจะสามารถแทนที่สัญญาส่วนใหญ่ด้วย async ได้แล้วรออยู่

ทำไม async จึงจำเป็นต้องรอเมื่อสัญญาจะทำงานที่คล้ายกัน?

async รอการแก้ปัญหาที่ใหญ่กว่าหรือไม่? หรือเป็นเพียงวิธีแก้ปัญหาที่แตกต่างกันในการเรียกกลับนรก?

ดังที่ฉันได้กล่าวไปก่อนหน้านี้ฉันสามารถใช้คำสัญญาและการเชื่อมต่อได้รอคอยที่จะแก้ไขปัญหาเดียวกัน มีอะไรเฉพาะที่ async รอการแก้ไข?

หมายเหตุเพิ่มเติม:

ฉันใช้ async รอและสัญญาในโครงการ React และโมดูล Node.js อย่างกว้างขวาง โดยเฉพาะอย่างยิ่งการตอบสนองเป็นนกรุ่นแรก ๆ และใช้คุณลักษณะ ECMAScript 6 และ ECMAScript 7 จำนวนมาก


3
บล็อกรหัสแรกของคุณดูเหมือนจะใช้สัญญาสำหรับการดำเนินการแบบซิงโครนัส ทำไมคุณจะทำเช่นนั้น? โดยธรรมชาติแล้วการซิงโครนัสนั้นง่ายกว่าในการเขียนโค้ดดังนั้นจึงควรมีเหตุผลเพียงเล็กน้อยที่จะรวมการดำเนินการแบบซิงโครนัสไว้ในสัญญาและบังคับให้เป็น async
jfriend00

@ jfriend00 ใช่คุณพูดถูก แก้ไขรหัส ขอบคุณ.
bozzmob

2
คุณยังคงพยายามใช้เครื่องมือ async กับฟังก์ชันซิงโครนัส - ตอนนี้อยู่ในบล็อคโค้ดทั้งสอง ทำไม?
jfriend00

@ jfriend00 โอเค ที่นี่ผมมีรหัสของฉันgist.github.com/bozzmob/26d38b83dc37d1be37f5 ช่วยบอกหน่อยได้ไหมว่าฉันทำอะไรผิด?
bozzmob

10
ดูเหมือนว่าคุณต้องอ่านหนังสือมากมายเพื่อทำความเข้าใจว่า async และการรอคอยมีไว้เพื่ออะไร นี่คือบทความบางส่วน: ถนนยาวเพื่อ Async / รอใน JavaScriptและลดความซับซ้อนของการเข้ารหัสแบบ Asynchronous กับฟังก์ชั่น ES7 Asyncและฝึกฝนสัตว์ตรงกันกับ ES7
jfriend00

คำตอบ:


84

ทำไม async จึงจำเป็นต้องรอเมื่อสัญญาทำงานคล้ายกัน? async รอการแก้ปัญหาที่ใหญ่กว่าหรือไม่?

async/awaitเพียงแค่ให้ความรู้สึกซิงโครนัสกับรหัสอะซิงโครนัส มันเป็นน้ำตาลสังเคราะห์ที่สวยงามมาก

สำหรับการสืบค้นและการจัดการข้อมูลแบบง่ายๆ Promises อาจเป็นเรื่องง่าย แต่ถ้าคุณพบในสถานการณ์ที่มีการจัดการข้อมูลที่ซับซ้อนและไม่มีอะไรเกี่ยวข้องก็จะง่ายขึ้นที่จะเข้าใจว่าเกิดอะไรขึ้นหากโค้ดดูราวกับว่าเป็นแบบซิงโครนัส (หากต้องการกล่าวอีกนัยหนึ่งคือ ไวยากรณ์ในและของตัวเองเป็นรูปแบบของ "ความซับซ้อนโดยบังเอิญ" ที่async/awaitสามารถแก้ไขได้)

หากคุณสนใจที่จะรู้คุณสามารถใช้ห้องสมุดเช่นco(ข้างเครื่องกำเนิดไฟฟ้า) เพื่อให้ความรู้สึกแบบเดียวกัน สิ่งต่างๆเช่นนี้ได้รับการพัฒนาขึ้นเพื่อแก้ปัญหาที่async/awaitสามารถแก้ไขได้ในที่สุด (โดยกำเนิด)


1
โปรดอธิบายให้ละเอียดว่า "ความซับซ้อนโดยบังเอิญ" หมายถึงอะไร นอกจากนี้เมื่อพูดถึงประสิทธิภาพแล้วไม่มีความแตกต่างระหว่างทั้งสอง?
bozzmob

@bozzmob, shaffner.us/cs/papers/tarpit.pdf <- เขาอธิบาย "ความซับซ้อนโดยบังเอิญ" ในนั้น สำหรับคำถามเกี่ยวกับประสิทธิภาพของคุณฉันสงสัยโดยเฉพาะอย่างยิ่งกับเครื่องยนต์ V8 ว่ามันคืออะไร ฉันแน่ใจว่ามีการทดสอบความสมบูรณ์แบบอยู่ที่นั่น แต่ฉันจะไม่กังวลกับเรื่องนั้นมากเกินไป อย่าเสียเวลาไปกับการเพิ่มประสิทธิภาพระดับไมโครเมื่อไม่จำเป็น
Josh Beam

1
ขอบคุณมาก! นี่คือข้อมูลที่ดีที่ฉันได้รับจากคุณ และใช่จะไม่มองไปที่การเพิ่มประสิทธิภาพขนาดเล็ก
bozzmob

ฉันพบว่าคำอธิบายนี้มีประโยชน์nikgrozev.com/2015/07/14/…
mwojtera

36

Async / Await ให้ไวยากรณ์ที่ดีกว่าในสถานการณ์ที่ซับซ้อนมากขึ้น โดยเฉพาะอย่างยิ่งการจัดการกับสิ่งที่ลูปหรือโครงสร้างอื่น ๆ บางอย่างเช่น/trycatch

ตัวอย่างเช่น:

while (!value) {
  const intermediate = await operation1();
  value = await operation2(intermediate);
}

ตัวอย่างนี้น่าจะซับซ้อนกว่ามากเพียงแค่ใช้คำสัญญา


นี่เป็นตัวอย่างที่ดีในการทำความเข้าใจเช่นเดียวกัน ดังนั้นเมื่อพูดถึงประสิทธิภาพแล้วไม่มีความแตกต่างระหว่างทั้งสอง? และจะใช้โค้ดไหนดีกว่ากัน? Async Await ดูเหมือนจะดีขึ้นหลังจากเห็นตัวอย่างของคุณอย่างน้อยที่สุด
bozzmob

1
@bozzmob: ประสิทธิภาพไม่มีความแตกต่าง หากคุณสะดวกที่จะใช้ async / await ฉันขอแนะนำ ฉันยังไม่ได้ใช้เองเพราะมันไม่ได้เป็นส่วนหนึ่งของมาตรฐานอย่างเป็นทางการ
Stephen Cleary

ใช่ฉันยอมรับว่ามันไม่ใช่ส่วนหนึ่งของมาตรฐาน แต่ในกรณีของ ReactJS (ตอบสนองเนทีฟโดยเฉพาะ) ฉันถูกบังคับให้ใช้ในบางส่วนของโค้ด ดังนั้นครึ่งหนึ่งของพวกเขาคือคำสัญญาและอีกครึ่งหนึ่งไม่เหมือนกันที่รอคอย ฉันถามคำถามเหล่านั้นกับคุณ ขอบคุณสำหรับข้อมูลที่ต้องการ
bozzmob

1
ฉันคิดว่าคนจำนวนมากสับสนและ / หรือเข้าใจผิดเมื่อไม่มีใครใช้บล็อก try / catch ในตัวอย่างโค้ดของพวกเขา
Augie Gardner

คุณหมายถึงอย่างนั้นเหรอ? const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux

17

ทำไม async จึงจำเป็นต้องรอเมื่อสัญญาทำงานคล้ายกัน? async รอการแก้ปัญหาที่ใหญ่กว่าหรือไม่? หรือเป็นเพียงวิธีแก้ปัญหาที่แตกต่างในการเรียกกลับนรก? ดังที่ได้กล่าวไปก่อนหน้านี้ฉันสามารถใช้ Promises และ Async รอเพื่อแก้ปัญหาเดียวกัน มีอะไรที่เฉพาะเจาะจงที่ Async Await แก้ไขหรือไม่?

สิ่งแรกที่คุณต้องเข้าใจว่าasync/ awaitวากยสัมพันธ์เป็นเพียงน้ำตาลวากยสัมพันธ์ซึ่งมีไว้เพื่อเพิ่มพูนสัญญา ในความเป็นจริงค่าตอบแทนของasyncฟังก์ชันคือสัญญา async/ awaitsyntax ช่วยให้เราสามารถเขียน asynchronous ในลักษณะซิงโครนัสได้ นี่คือตัวอย่าง:

การผูกมัดสัญญา:

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}

Async ฟังก์ชัน:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

ในตัวอย่างข้างต้นการawaitรอให้สัญญา ( fetch(url)) ได้รับการแก้ไขหรือปฏิเสธ หากคำสัญญาได้รับการแก้ไขค่าจะถูกเก็บไว้ในresponseตัวแปรและหากคำสัญญาถูกปฏิเสธก็จะส่งข้อผิดพลาดและเข้าสู่catchบล็อก

เราสามารถเห็นได้แล้วว่าการใช้async/ awaitอาจอ่านได้ง่ายกว่าการผูกมัดสัญญา โดยเฉพาะอย่างยิ่งเมื่อจำนวนสัญญาที่เราใช้เพิ่มขึ้น ทั้งสัญญาผูกมัดและasync/ awaitแก้ปัญหานรกเรียกกลับและวิธีที่คุณเลือกเป็นเรื่องของความชอบส่วนบุคคล


12

เปรียบเทียบข้อดีข้อเสีย

JavaScript ธรรมดา

  • ข้อดี
  • ไม่ต้องใช้ไลบรารีหรือเทคโนโลยีเพิ่มเติมใด ๆ
  • O ff ให้ประสิทธิภาพที่ดีที่สุด
  • ให้ระดับความเข้ากันได้ดีที่สุดกับไลบรารีของบุคคลที่สาม
  • อนุญาตให้สร้างเฉพาะกิจและอัลกอริทึมขั้นสูงเพิ่มเติม
  • จุดด้อย
  • อาจต้องใช้โค้ดพิเศษและอัลกอริทึมที่ค่อนข้างซับซ้อน

Async (ไลบรารี)

  • ข้อดี
  • Simpli เป็นรูปแบบการควบคุมที่พบบ่อยที่สุด
  • ยังคงเป็นโซลูชันแบบโทรกลับ
  • ประสิทธิภาพที่ดี
  • จุดด้อย
  • เปิดตัวการพึ่งพาภายนอก
  • อาจจะยังไม่เพียงพอสำหรับ fl ows ขั้นสูง

สัญญา

  • ข้อดี
  • ง่ายอย่างมากรูปแบบการควบคุมที่พบบ่อยที่สุด fl โอ๊ย
  • การจัดการข้อผิดพลาดที่แข็งแกร่ง
  • เป็นส่วนหนึ่งของข้อมูลจำเพาะ ES2015
  • รับประกันการร้องขอรอการตัดบัญชีของ onFulfilled และ onRejected
  • จุดด้อย
  • ต้องการ API ตามการโทรกลับที่สัญญาไว้
  • เปิดตัวผลงานยอดฮิตเล็ก ๆ

เครื่องกำเนิดไฟฟ้า

  • ข้อดี
  • ทำให้ API ที่ไม่ปิดกั้นดูเหมือนเป็นการปิดกั้น
  • Simpli fi es จัดการข้อผิดพลาด
  • ส่วนหนึ่งของข้อมูลจำเพาะ ES2015
  • จุดด้อย
  • ต้องมีไลบรารีการควบคุมเสริม ow
  • ยังคงต้องมีการเรียกกลับหรือสัญญาว่าจะใช้ fl ows ที่ไม่ใช่ลำดับ
  • ต้องใช้ thunkify หรือให้สัญญากับ API ที่อิงตามผู้สร้าง

Async รออยู่

  • ข้อดี
  • ทำให้ API ที่ไม่ปิดกั้นดูเหมือนการบล็อก
  • ไวยากรณ์ที่สะอาดและใช้งานง่าย
  • จุดด้อย
  • ต้องใช้ Babel หรือทรานสไพเลอร์อื่น ๆ และการกำหนดค่าบางอย่างเพื่อใช้ในปัจจุบัน

สิ่งนี้คัดลอกมาจากไหน? อย่างน้อยก็มีบางส่วนในหน้า 136-137 ในหนังสือNode.js Design Patterns (พิมพ์ครั้งที่สอง) (ISBN-10: 1785885588)
Peter Mortensen

6

Async / await สามารถช่วยทำให้โค้ดของคุณสะอาดขึ้นและอ่านได้ง่ายขึ้นในกรณีที่คุณต้องการขั้นตอนการควบคุมที่ซับซ้อน นอกจากนี้ยังสร้างโค้ดที่เป็นมิตรกับการดีบักมากขึ้น try/catchและทำให้มันเป็นไปได้ที่จะจัดการกับข้อผิดพลาดทั้งซิงโครและไม่ตรงกันมีเพียง

ฉันเพิ่งเขียนโพสต์นี้เพื่อแสดงข้อดีของ async / รอคำสัญญาในกรณีการใช้งานทั่วไปพร้อมตัวอย่างโค้ด: 6 เหตุผลที่ JavaScript Async / Await Blows Promises Away (บทช่วยสอน)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.