مقدمة إلى ECMAScript 2017 (ES8)

جدول المحتويات


مقدمة
ES7 نظرة عامة
1. Object.entries
2. Object.values
3. String.prototype.padEnd
4. String.prototype.padStart
5. Object.getOwnPropertyDescriptor
6. زائدة الفواصل
7. SharedArrayBuffer
8. الذرة
9. وظائف المتزامن

مقدمة


مرحبًا ، في الماضي ، فكرت بالفعل في الابتكارات في ES6 والآن حان الوقت لتفكيك ES8 لأنه جلب الكثير من الأشياء الجديدة. لم أعتبر ES7 (2016) بشكل منفصل ، لأن هذا الإصدار لم يجلب سوى اثنين من الابتكارات. هذا هو Array.prototype.includes () ومشغل الأس. ولكن لا يزال ، قبل البدء في ES8 ، دعونا ننظر إلى الابتكارات من ES7.

ES7 نظرة عامة


تحدد الطريقة () ما إذا كانت المصفوفة تحتوي على عنصر معين ، مع إعادة صواب أم خطأ اعتمادا على هذا.

Array.prototype.includes(searchElement[, fromIndex = 0]) : Boolean 

searchElement - العنصر للبحث.

fromIndex - الموضع في الصفيف الذي تبدأ منه عملية البحث عن عنصر searchElement. بالنسبة للقيم السالبة ، يتم إجراء البحث بدءًا من الفهرس array.length + fromIndex تصاعديًا. القيمة الافتراضية هي 0.

أمثلة

 [1, 2, 3].includes(2); // true [1, 2, 3].includes(4); // false [1, 2, 3].includes(3, 3); // false [1, 2, 3].includes(3, -1); // true [1, 2, NaN].includes(NaN); // true 

يتضمن () يمكن تطبيقها على أنواع أخرى من الكائنات (على سبيل المثال ، كائنات تشبه الصفيف). مثال: استخدام الأسلوب include () في كائن الوسائط.

 (function() { console.log([].includes.call(arguments, 'a')); // true console.log([].includes.call(arguments, 'd')); // false })('a','b','c'); 

إرجاع عامل الأس (**) قوة ذات أساس a و a طبيعي a b. رفع إلى قوة ب.

 a ** b 

أمثلة

 2 ** 3 // 8 3 ** 2 // 9 3 ** 2.5 // 15.588457268119896 10 ** -1 // 0.1 NaN ** 2 // NaN 2 ** 3 ** 2 // 512 2 ** (3 ** 2) // 512 (2 ** 3) ** 2 // 64 -(2 ** 2) // -4 (-2) ** 2 // 4 

1. Object.entries


إرجاع Object.entries () صفيف عناصره صفائف المطابقة الخاصية تعداد الزوج [مفتاح ، قيمة] العثور مباشرة في الكائن. ترتيب الخصائص هو نفسه عند التنقل بين خصائص كائن يدويًا.

 Object.entries(obj) : Array 

obj - كائن سيتم إرجاع خصائصه المذكورة كصفيف [مفتاح ، قيمة].

إرجاع Object.entries () الخصائص بنفس الترتيب كما هو الحال في for ... في الحلقة (الفرق هو أن for-in يسرد أيضًا الخصائص من سلسلة النموذج الأولي). ترتيب العناصر في الصفيف الذي إرجاع Object.entries () مستقلة عن كيفية تعريف الكائن. إذا كانت هناك حاجة إلى ترتيب محدد ، فيجب تصنيف المصفوفة قبل استدعاء الطريقة.

أمثلة

 var obj = { foo: "bar", baz: 42 }; console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ] //    var obj = { 0: 'a', 1: 'b', 2: 'c' }; console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ] //    c random   var an_obj = { 100: 'a', 2: 'b', 7: 'c' }; console.log(Object.entries(an_obj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ] // getFoo  ,    var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } }); my_obj.foo = "bar"; console.log(Object.entries(my_obj)); // [ ['foo', 'bar'] ] // non-object     object console.log(Object.entries("foo")); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ] let obj = { one: 1, two: 2 }; for (let [k,v] of Object.entries(obj)) console.log(`${JSON.stringify(k)}: ${JSON.stringify(v)}`) // "one": 1 // "two": 2 

تحويل كائن إلى خريطة

يقبل مُنشئ Map () الجديد تكرار القيم. باستخدام Object.entries ، يمكنك بسهولة تحويل كائن إلى خريطة. هذا أكثر إيجازاً من استخدام مجموعة من صفيفين من العناصر ، ولكن يمكن أن تكون المفاتيح سلاسل فقط.

 var obj = { foo: "bar", baz: 42 }; var map = new Map(Object.entries(obj)); console.log(map); // Map {"foo" => "bar", "baz" => 42} 

لماذا هي قيمة الإرجاع Object.entries () صفيف وليس التكرار؟
حالة الاستخدام المطابق في هذه الحالة هي Object.keys () ، وليس ، على سبيل المثال ، Map.prototype.entries ().

لماذا Object.entries () بإرجاع الخصائص الأصلية التعداد فقط مع مفاتيح السلسلة؟

مرة أخرى ، يتم ذلك لمطابقة Object.keys (). تتجاهل هذه الطريقة أيضًا الخصائص التي تكون مفاتيحها أحرف. في النهاية ، قد يكون هناك أسلوب Reflect.ownEntries () بإرجاع كافة الخصائص الخاصة به.

انظر object.entries في المواصفات الرسمية ، وكذلك في MDN Web Docs .

2. Object.values


إرجاع Object.values ​​() صفيف عناصره هي قيم الخصائص تعداد الموجودة في الكائن. الترتيب هو نفسه كما لو كنت تتجول عبر الكائن يدويًا.

 Object.values(obj) : Array 

obj - كائن سيتم إرجاع قيم الخصائص المميزة له.

إرجاع الأسلوب Object.values ​​() صفيف قيم الخصائص تعداد الكائن في نفس الترتيب كـ لـ ... في حلقة. الفرق بين الحلقة والأسلوب هو أن الحلقة تسرد الخصائص من وإلى سلسلة النموذج الأولي.

أمثلة

 var obj = { foo: "bar", baz: 42 }; console.log(Object.values(obj)); // ['bar', 42] //    var obj = { 0: 'a', 1: 'b', 2: 'c' }; console.log(Object.values(obj)); // ['a', 'b', 'c'] 

الفرق بين Object.entries و Object.values ​​() هو أن الأول يعرض صفيفًا من المصفوفات التي تحتوي على اسم وقيمة الخاصية ، بينما تقوم الثانية بإرجاع صفيف فقط بقيمة الخصائص.

مثال الفرق بين Object.values ​​() و Object.entries ()

 const object = { a: 'somestring', b: 42, c: false }; console.log(Object.values(object)); // ["somestring", 42, false] console.log(Object.entries(object)); // [ ["a", "somestring"], ["b", 42], ["c", false] ] 

راجع Object.values ​​() في المواصفات الرسمية ، وكذلك في MDN Web Docs .

3. String.prototype.padEnd


يكمل الأسلوب padEnd () السطر الحالي بسلسلة معينة (تكرارًا أخيرًا) بحيث تصل السلسلة الناتجة إلى الطول المحدد. يتم تطبيق الإضافة في نهاية (يمين) السطر الحالي.

 String.prototype.padEnd(maxLength [ , fillString ]) : String 

maxLength - طول الصف الناتج بعد الصف الحالي مبطن. إذا كانت هذه المعلمة أقل من طول السطر الحالي ، فسيتم إرجاع السطر الحالي كما هو.
fillString - سلسلة لتكملة السطر الحالي بـ. إذا كان هذا الخط طويل جدًا ، فسيتم اقتطاعه وسيتم تطبيق أقصى اليسار. "" (0x0020 SPACE) هي القيمة الافتراضية لهذه المعلمة.

أمثلة

 'abc'.padEnd(10); // "abc " 'abc'.padEnd(10, "foo"); // "abcfoofoof" 'abc'.padEnd(6,"123456"); // "abc123" 

تشمل حالات الاستخدام لنشر السلاسل ما يلي:

  • إضافة عداد أو معرف إلى اسم ملف أو عنوان URL: 'file 001.txt'
  • محاذاة إخراج وحدة التحكم: "اختبار 001: ✓"
  • طباعة أرقام ست عشرية أو ثنائية مع عدد ثابت من الأرقام: '0x00FF'

راجع String.prototype.padEnd في المواصفات الرسمية ، وكذلك في MDN Web Docs .

4. String.prototype.padStart


تملأ طريقة padStart () السطر الحالي بسطر آخر (عدة مرات ، إذا لزم الأمر) حتى يصل الخط الناتج إلى الطول المحدد. يتم التعبئة في بداية (يسار) السطر الحالي.

 String.prototype.padStart(maxLength [, fillString]) : String 

maxLength - طول سطر الملخص بعد اكتمال السطر الحالي. إذا كانت القيمة أقل من طول السطر الحالي ، فسيتم إرجاع السطر الحالي بدون تغيير.

fillString - سلسلة لملء السطر الحالي. إذا كانت هذه السلسلة طويلة جدًا لطول معين ، فسيتم اقتطاعها. القيمة الافتراضية هي "" (0x0020 SPACE).

أمثلة

 'abc'.padStart(10); // " abc" 'abc'.padStart(10, "foo"); // "foofoofabc" 'abc'.padStart(6,"123465"); // "123abc" 'abc'.padStart(8, "0"); // "00000abc" 'abc'.padStart(1); // "abc" 

لماذا لا يتم استخدام أساليب الحشو padLeft و padRight؟

بالنسبة للغات ثنائية الاتجاه أو من اليمين إلى اليسار ، لا تعمل مصطلحي "يسار" و "يمين". لذلك ، فإن تسمية padStart و padEnd تتبع الأسماء الموجودة بدءًا من startWith و endWith.

راجع String.prototype.padStart في المواصفات الرسمية ، وكذلك في MDN Web Docs .

5. Object.getOwnPropertyDescriptor


إرجاع الأسلوب Object.getOwnPropertyDescriptor () واصف خاصية لخاصيته (أي ، الموجود مباشرة في الكائن ، ولم يتم تلقيها من خلال سلسلة النموذج الأولي) للكائن الذي تم تمريره. إذا كانت الخاصية غير موجودة ، فستُرجع غير محدد.

 Object.getOwnPropertyDescriptor(obj, prop) : Object 

obj - الكائن الذي يتم فيه البحث عن الخاصية.

prop - اسم العقار الذي سيتم إرجاع وصفه.

تسمح لك هذه الطريقة بعرض الوصف الدقيق للعقار. تتكون خاصية في JavaScript من اسم السلسلة وواصف الخاصية.

واصف الخاصية هو سجل يحتوي على بعض السمات التالية:

  • القيمة - القيمة المرتبطة بالخاصية (فقط في واصف البيانات).
  • قابل للكتابة - صحيح إذا كانت القيمة المرتبطة بالخاصية يمكن تغييرها ، وإلا كانت خاطئة (فقط في واصف البيانات).
  • get - دالة تقوم بإرجاع قيمة الخاصية ، أو غير محددة إذا لم يكن هناك مثل هذه الوظيفة (فقط في واصف الوصول).
  • set - دالة تغير قيمة الخاصية ، أو غير محددة إذا لم يكن هناك مثل هذه الوظيفة (فقط في واصف الوصول).
  • قابل للتكوين - صحيح إذا كان يمكن تغيير نوع المقبض لهذه الخاصية وإذا كان يمكن إزالة الخاصية من الكائن الذي يحتوي عليها ، أو غير ذلك.
  • تعداد - صحيح إذا كانت هذه الخاصية متوفرة عند سرد خصائص الكائن الذي يحتوي عليها ، وإلا كانت خاطئة.

أمثلة

 obj = { get foo() { return 10; } }; console.log(Object.getOwnPropertyDescriptor(obj, 'foo')); // {set: undefined, enumerable: true, configurable: true, get: ƒ} obj2 = { bar: 42 }; console.log(Object.getOwnPropertyDescriptor(obj2, 'bar')); // {value: 42, writable: true, enumerable: true, configurable: true} 

استخدام الحالات لـ Object.getOwnPropertyDescriptor ()


أول حالة استخدام: نسخ الخصائص إلى كائن
بدءًا من ES6 ، يحتوي JavaScript بالفعل على طريقة أداة لنسخ الخصائص: Object.assign (). ومع ذلك ، تستخدم هذه الطريقة عمليات بسيطة للحصول على خاصية وتعيينها لنسخ خاصية يكون المفتاح هو المفتاح:

 const value = source[key]; // get target[key] = value; // set 
هذا يعني أنه لا يقوم بنسخ الخصائص بشكل صحيح بسمات أخرى غير الخصائص المحددة افتراضيًا (طرق الحصول ، الإعداد ، الكتابة ، إلخ). يوضح المثال التالي هذا القيد. يحتوي مصدر الكائن على برنامج تثبيت مفتاحه foo:
 const source = { set foo(value) { console.log(value); } }; console.log(Object.getOwnPropertyDescriptor(source, 'foo')); // { get: undefined, set: [Function: foo], enumerable: true, configurable: true } 

فشل استخدام Object.assign () لنسخ خاصية foo إلى الكائن الهدف:

 const target1 = {}; Object.assign(target1, source); console.log(Object.getOwnPropertyDescriptor(target1, 'foo')); // { value: undefined, writable: true, enumerable: true, configurable: true } 
لحسن الحظ ، فإن استخدام Object.getOwnPropertyDescriptors () مع Object.defineProperties () يعمل:

 const target2 = {}; Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source)); console.log(Object.getOwnPropertyDescriptor(target2, 'foo')); // { get: undefined, set: [Function: foo], enumerable: true, configurable: true } 

حالة الاستخدام الثاني : كائنات الاستنساخ
يشبه الاستنساخ الضحل خصائص النسخ ، لذلك يعد Object.getOwnPropertyDescriptors () خيارًا جيدًا هنا أيضًا.

هذه المرة نستخدم Object.create () ، والذي له معلمتان:
تحدد المعلمة الأولى النموذج الأولي للكائن المرتجع.

المعلمة الثانية الاختيارية هي مجموعة من واصفات الخصائص ، مماثلة لتلك التي تم إرجاعها بواسطة Object.getOwnPropertyDescriptors ().

 const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj)); 

حالة الاستخدام الثالثة : حرفية كائن عبر النظام الأساسي مع نماذج تعسفية.

تتمثل أفضل طريقة لغوية في استخدام كائن حرفي لإنشاء كائن بنموذج أولي تعسفي في استخدام خاصية __proto__ الخاصة:

 const obj = { __proto__: prot, foo: 123, }; 

للأسف ، هذه الميزة مضمونة لتكون موجودة فقط في المتصفحات. الحل العام هو Object.create () والتخصيص:

 const obj = Object.create(prot); obj.foo = 123; 

ولكن يمكنك أيضًا استخدام Object.getOwnPropertyDescriptors ():

 const obj = Object.create( prot, Object.getOwnPropertyDescriptors({ foo: 123, }) ); 

بديل آخر هو Object.assign ():

 const obj = Object.assign( Object.create(prot), { foo: 123, } ); 

المأزق: طرق النسخ باستخدام السوبر.

يرتبط الأسلوب الذي يستخدمه super بإحكام بكائنه الرئيسي (الكائن الذي يتم تخزينه به). لا توجد حاليًا طريقة لنسخ أو نقل هذه الطريقة إلى كائن آخر.

راجع Object.getOwnPropertyDescriptor في المواصفات الرسمية ، وكذلك في MDN Web Docs .

6. زائدة الفواصل


تعليق الفواصل (فواصل زائدة) - يمكن أن يكون مفيدًا عند إضافة عناصر أو معلمات أو خصائص جديدة إلى شفرة JavaScript. إذا كنت ترغب في إضافة خاصية جديدة ، يمكنك ببساطة إضافة سطر جديد دون تغيير السطر السابق ، إذا كانت الفاصلة المعلقة مستخدمة بالفعل في ذلك. هذا يجعل الاختلافات في الإصدار تحكم نظافة وتغييرات رمز يمكن أن يكون أقل إزعاجاً.

شنقا الفواصل في الحرفي


المصفوفات

يتجاهل JavaScript الفواصل المعلقة في المصفوفات:

 var arr = [ 0, 1, 2, ]; console.log(arr); // [0, 1, 2] console.log(arr.length); // 3 var arr2 = [0, 1, 2,,,]; console.log(arr2.length); // 5 arr2.forEach((e) => console.log(e)); // 0 1 2 console.log(arr.map((e) => e)); // 0 1 2 

إذا تم استخدام أكثر من نقطة تعلق ، سيتم إنشاء ثقوب. تسمى المصفوفة ذات "الثقوب" متناثر (المصفوفة الكثيفة لا تحتوي على "فتحات"). عند تكرار صفيف باستخدام ، على سبيل المثال ، Array.prototype.forEach () أو Array.prototype.map () ، سيتم تخطي الثقوب.

الكائنات

 var object = { foo: "bar", baz: "qwerty", age: 42, }; console.log(object); // {foo: "bar", baz: "qwerty", age: 42} 

شنقا الفواصل في الوظائف


تعريف المعلمة

التعريفات التالية لمعلمات الوظيفة صالحة ومكافئة لبعضها البعض. لا تؤثر فواصل التعلق على خاصية طول دالة أو كائن وسيطاتها.

 function f(p) {} function f(p,) {} (p) => {}; (p,) => {}; 

تعريف الطريقة

تعمل الفاصلة المعلقة أيضًا مع تحديد طرق للفئات أو الكائنات.

 class C { one(a,) {}, two(a, b,) {}, } var obj = { one(a,) {}, two(a, b,) {}, }; 

استدعاء وظيفة

استدعاءات الوظائف التالية صالحة وتعادل بعضها البعض.

 f(p); f(p,); Math.max(10, 20); Math.max(10, 20,); 

فواصل معلقة غير صالحة

تحديد معلمات الدالة أو استدعاء دالة تحتوي فقط على فاصلة سيؤدي إلى رفع SyntaxError. بالإضافة إلى ذلك ، عند استخدام المعلمات المتبقية ، لا يُسمح بتعليق الفواصل.

 function f(,) {} // SyntaxError: missing formal parameter (,) => {}; // SyntaxError: expected expression, got ',' f(,) // SyntaxError: expected expression, got ',' function f(...p,) {} // SyntaxError: parameter after rest parameter (...p,) => {} // SyntaxError: expected closing parenthesis, got ',' 

شنقا الفواصل في تدمير


يمكن أيضًا استخدام فواصل معلقة على اليسار عند استخدام الواجب المدمر.

 //      [a, b,] = [1, 2]; //      var o = { p: 42, q: true, }; var {p, q,} = o; 

مرة أخرى ، باستخدام المعلمات المتبقية ، سيتم طرح SyntaxError.

 var [a, ...b,] = [1, 2, 3]; // Uncaught SyntaxError: Rest element must be last element 

JSON التعلق الفواصل


يُسمح بتعليق الفواصل في كائن فقط في ECMAScript 5. نظرًا لأن JSON يستند إلى بناء جملة JavaScript أقدم من ES5 ، فإن الفواصل المعلقة غير مسموح بها في JSON.

كلا الخطين رمي SyntaxError

 JSON.parse('[1, 2, 3, 4, ]'); JSON.parse('{"foo" : 1, }'); // Uncaught SyntaxError: Unexpected token ] in JSON // Uncaught SyntaxError: Unexpected token } in JSON 

لماذا شنقا الفواصل مفيدة؟


هناك نوعان من الفوائد.

أولاً ، إعادة ترتيب العناصر أسهل لأنك لا تحتاج إلى إضافة أو إزالة فواصل إذا كان العنصر الأخير يغير موضعه.

ثانياً ، يساعد أنظمة التحكم في الإصدار على تتبع ما تغير بالفعل. على سبيل المثال ، من:

 [ 'Foo' ] : [ 'Foo', '' ] 

يؤدي إلى تمييز كل من السطر بـ "foo" والخط الذي يحتوي على "bar" على أنه تم تغييره ، على الرغم من أن التغيير الحقيقي الوحيد هو إضافة السطر الأخير.

راجع تتبع الفواصل في MDN Web Docs .

7. SharedArrayBuffer


يتم استخدام كائن SharedArrayBuffer لإنشاء مخزن مؤقت ذي طول ثابت لتخزين البيانات الثنائية البدائية ، على غرار كائن ArrayBuffer ، ولكن في المقابل ، يمكن استخدام مثيلات SharedArrayBuffer لإنشاء طريقة عرض على الذاكرة المشتركة. SharedArrayBuffer لا يمكن قطع الاتصال.
 new SharedArrayBuffer(length) : Object 
طول - الحجم بالبايت لإنشاء صفيف المخزن المؤقت.

الإرجاع - كائن SharedArrayBuffer جديد من الطول المحدد. محتوياته بعد التهيئة هي 0.

لمشاركة الذاكرة باستخدام كائن SharedArrayBuffer بين وكيل في المجموعة وآخر (يمكن أن يكون الوكيل البرنامج الرئيسي لصفحة الويب أو أحد عمال الويب) ، يتم استخدام postMessage والاستنساخ المهيكل.

تقبل خوارزمية الاستنساخ المهيكلة SharedArrayBuffers و TypedArrays المعينين إلى SharedArrayBuffers. في كلتا الحالتين ، يتم تمرير كائن SharedArrayBuffer إلى جهاز الاستقبال ، مما يؤدي إلى إنشاء كائن SharedArrayBuffer خاص جديد داخل وكيل الاستلام (كما هو الحال في ArrayBuffer). ومع ذلك ، فإن كتلة البيانات المشتركة المشار إليها من قبل كل من الكائنات SharedArrayBuffer هي نفس كتلة البيانات ، وسوف تصبح تأثيرات الطرف الثالث في الكتلة في أحد الوكلاء مرئية في العامل الآخر.

 var sab = new SharedArrayBuffer(1024); worker.postMessage(sab); 

يمكن إنشاء الذاكرة المشتركة وتغييرها في وقت واحد في العمال أو الخيط الرئيسي. اعتمادًا على النظام (CPU ، OS ، المتصفح) ، قد يستغرق الأمر بعض الوقت حتى يتم نشر التغييرات على جميع السياقات. للتزامن ، هناك حاجة إلى العمليات الذرية.

مخازن المصفوفة المشتركة هي لبنة بناء بدائية لتجريد التوازي على مستوى أعلى. تسمح لك بمشاركة بايت وحدات SharedArrayBuffer بين عدة عمال ومؤشر الترابط الرئيسي (تتم مشاركة المخزن المؤقت للوصول إلى بايت ، لفه في صفيف مكتوب). هذا النوع من التبادل له ميزتان:
يمكنك تبادل البيانات بين العمال بشكل أسرع.

يصبح التنسيق بين العمال أسهل وأسرع (مقارنة بـ postMessage ()).

تنفيذ العامل على النحو التالي.

 // worker.js self.addEventListener ('message', function (event) { const {sharedBuffer} = event.data; const sharedArray = new Int32Array (sharedBuffer); // ··· }); 

أولاً ، نقوم باستخراج المخزن المؤقت للصفيف المشترك الذي تم إرساله إلينا ، ثم نلفه في صفيف مكتوب حتى نتمكن من استخدامه محليًا.

خصائص وطرق SharedArrayBuffer.

SharedArrayBuffer.length - طول مُنشئ SharedArrayBuffer التي تكون قيمتها 1.
SharedArrayBuffer.prototype - يسمح بخصائص إضافية لجميع كائنات SharedArrayBuffer.

مثيلات SharedArrayBuffer
الخصائص

SharedArrayBuffer.prototype.constructor - يعرّف الدالة التي تنشئ نموذجًا أوليًا لكائن. القيمة الأولية هي مُنشئ SharedArrayBuffer المضمّن القياسي.

SharedArrayBuffer.prototype.byteLength (للقراءة فقط) - حجم الصفيف بالبايت. يتم تعيين هذا عند إنشاء الصفيف ولا يمكن تغييره.

طرق

SharedArrayBuffer.prototype.slice () - إرجاع SharedArrayBuffer جديد تكون محتوياته نسخة من وحدات البايت الخاصة بهذا SharedArrayBuffer من البداية ، بما في ذلك إلى نهايتها ، الحصرية. إذا كانت البداية أو النهاية سالبة ، فهذا يشير إلى الفهرس من نهاية المصفوفة ، وليس من البداية. تحتوي هذه الطريقة على نفس الخوارزمية مثل Array.prototype.slice ().

 //  SharedArrayBuffer     const buffer = new SharedArrayBuffer(16); const int32View = new Int32Array(buffer); //  view // produces Int32Array [0, 0, 0, 0] int32View[1] = 42; const sliced = new Int32Array(buffer.slice(4,12)); console.log(sliced); // Int32Array [42, 0] 

 sab.slice([begin, end]) : Object 

تبدأ - مؤشر الصفر الذي يبدأ الاستخراج. يمكنك استخدام فهرس سلبي يشير إلى الإزاحة من نهاية التسلسل. شريحة (-2) تستخرج آخر عنصرين في تسلسل. إذا لم يتم تعريف البداية ، تبدأ الشريحة في الفهرس 0.
End (النهاية) - الفهرس القائم على الصفر والذي يجب إكمال الاستخراج.

على سبيل المثال ، تقوم الشريحة (1.4) باسترداد العنصر الثاني من خلال العنصر الرابع (العناصر ذات المؤشرات 1 و 2 و 3). يمكنك استخدام فهرس سلبي يشير إلى الإزاحة من نهاية التسلسل. تقوم شريحة (2 ، -1) باسترداد العنصر الثالث من خلال العنصر الثاني الأخير في التسلسل. إذا تم حذف النهاية ، فإن الشريحة تجلب خلال نهاية التسلسل (sab.byteLength).

أمثلة

 var sab = new SharedArrayBuffer(1024); sab.slice(); // SharedArrayBuffer { byteLength: 1024 } sab.slice(2); // SharedArrayBuffer { byteLength: 1022 } sab.slice(-2); // SharedArrayBuffer { byteLength: 2 } sab.slice(0, 1); // SharedArrayBuffer { byteLength: 1 } 

انظر SharedArrayBuffer في المواصفات الرسمية ، وكذلك في MDN Web Docs .

8. الذرة


يوفر كائن Atomics العمليات الذرية كطرق ثابتة. تستخدم مع كائن SharedArrayBuffer.

يتم تثبيت العمليات الذرية في وحدة Atomics. على عكس الكائنات العالمية الأخرى ، فإن Atomics ليس منشئًا. لا يمكن استخدامه مع المشغل الجديد أو لاستدعاء كائن Atomics كدالة. جميع خصائص وأساليب Atomics ثابتة (مثل كائن Math ، على سبيل المثال).

عند مشاركة الذاكرة ، يمكن لعدة مؤشرات ترابط قراءة وكتابة نفس البيانات إلى الذاكرة. تضمن العمليات الذرية كتابة القيم المتوقعة وقراءتها ، وإتمام العمليات قبل بدء العملية التالية ، ولن يتم إيقافها.

الخصائص


Atomics [Symbol.toStringTag] - قيمة هذه الخاصية هي Atomics.

طرق


العمليات الذرية

  • Atomics.add () - يضيف القيمة المقدمة إلى القيمة الحالية في الموضع المحدد في الصفيف. إرجاع القيمة السابقة في هذا الموضع.
  • Atomics.and () - يحسب bitwise AND في المصفوفة المحددة. إرجاع القيمة السابقة في هذا الموضع.
  • Atomics.compareExchange () - يحفظ القيمة المعروضة إلى الموضع المحدد للصفيف ، إذا كان مكافئًا للقيمة المقدمة. إرجاع القيمة السابقة.
  • Atomics.exchange() — . .
  • Atomics.load() — .
  • Atomics.or() — OR . .
  • Atomics.store() — . .
  • Atomics.sub() — . .
  • Atomics.xor() — XOR . .

الأسلوب الثابت Atomics.add () يضيف القيمة إلى الحالية الحالية في الموضع المحدد في الصفيف وإرجاع القيمة السابقة في هذا الموضع. تضمن هذه العملية الذرية عدم حدوث أي كتابة أخرى حتى تتم إعادة كتابة القيمة المعدلة.

 Atomics.add(typedArray, index, value) : mixed 

  • typedArray - مجموعة من الأعداد الصحيحة. Int8Array أو Uint8Array أو Int16Array أو Uint16Array أو Int32Array أو Uint32Array.
  • الفهرس - الموضع في typedArray لإضافة قيمة.
  • القيمة - الرقم المراد إضافته.
  • return - القيمة السابقة في الموضع المحدد (typedArray [index]).

  • يلقي TypeError إذا كان نوع typedArray ليس أحد أنواع الأعداد الصحيحة الصحيحة.
  • يلقي TypeError إذا كان نوع typedArray ليس من النوع العام.
  • الرميات RangeError إذا كان الفهرس خارج typedArray.

أمثلة

 var sab = new SharedArrayBuffer(1024); var ta = new Uint8Array(sab); Atomics.add(ta, 0, 12); //  0,   Atomics.load(ta, 0); // 12 

Atomics.add() , MDN Web Docs .

Wait notify


wait() wake() futexes («fast user-space mutex» — mutex ) Linux , true, .

Atomics.wait()
, -. «ok», «not-equal» «timed-out». , ( wait() ).

  • Atomics.wait() — , -. «ok», «not-equal» «timed-out». , ( wait() ).
  • Atomics.wake() — , . , .
  • Atomics.isLockFree(size) — , . true, ( ). .

مشاكل التحسين


التحسين يجعل التعليمات البرمجية غير متوقعة بين العمال. في مؤشرات الترابط المفردة ، يمكن للمترجمين تنفيذ عمليات تحسين تخرق الشفرة متعددة مؤشرات الترابط.

خذ على سبيل المثال الكود التالي:

 while (sharedArray [0] === 123); 

في مؤشر ترابط واحد ، لا تتغير قيمة SharedArray [0] أبدًا أثناء تنفيذ الحلقة (إذا كانت SharedArray عبارة عن صفيف أو صفيف مكتوب لم يتم إصلاحه بأي طريقة). لذلك ، يمكن تحسين الكود على النحو التالي:

 const tmp = sharedArray [0]; while (tmp === 123); 

ومع ذلك ، في الوضع متعدد مؤشرات الترابط ، لا يسمح لنا هذا التحسين باستخدام هذا القالب لانتظار التغييرات التي تم إجراؤها في سلسلة رسائل أخرى.

مثال آخر هو الكود التالي:

 // main.js sharedArray [1] = 11; sharedArray [2] = 22; 

في موضوع واحد ، يمكنك إعادة ترتيب عمليات الكتابة هذه لأنه لا يوجد شيء للقراءة بينهما. تواجه مؤشرات الترابط المتعددة مشاكل عندما تتوقع إجراء التسجيلات بترتيب معين:

 // worker.js while (sharedArray [2]! == 22); console.log (sharedArray [1]); // 0  11 

تجعل هذه الأنواع من التحسين من المستحيل تقريبًا مزامنة تصرفات العديد من العمال الذين يعملون على نفس المخزن المؤقت مع صفيف مشترك.

حل مشاكل التحسين


باستخدام المتغير العالمي Atomics ، والذي له طرق ثلاثة استخدامات رئيسية.

أول حالة الاستخدام: التزامن.

يمكن استخدام أساليب Atomics للتزامن مع العمال الآخرين. على سبيل المثال ، تسمح لك العمليتان التاليتان بقراءة البيانات وكتابتها ولا يتم إعادة ترتيبها بواسطة مترجمين:

 Atomics.load (TypedArray <T>, index) : T Atomics.store (TypedArray <T>, index, value: T) : T 

تتمثل الفكرة في استخدام العمليات العادية لقراءة وكتابة معظم البيانات ، بينما تضمن عمليات Atomics (التحميل والتخزين وغيرها) أن تكون القراءة والكتابة آمنة. غالبًا ما تستخدم آليات المزامنة الخاصة بك ، مثل الأقفال ، والتي تعتمد على Atomics.

هذا مثال بسيط للغاية يعمل دائمًا بفضل Atomics (لقد تخطيت إعداد SharedArray):

 // main.js console.log ('notified...'); Atomics.store (sharedArray, 0, 123); // worker.js while (Atomics.load (sharedArray, 0)! == 123); console.log ('notified'); 

حالة الاستخدام الثاني: في انتظار الإخطار .

استخدام حلقة من الوقت لانتظار الإخطار ليس فعالًا للغاية ، لذلك لدى Atomics عمليات تساعد: Atomics.wait (Int32Array ، الفهرس ، القيمة ، المهلة) و Atomics.wake (Int32Array ، الفهرس ، العدد).

حالة الاستخدام الثالثة: العمليات الذرية تعمل
بعض عمليات Atomics على حساب ولا يمكن مقاطعتها في نفس الوقت ، مما يساعد في التزامن. على سبيل المثال:

 Atomics.add (TypedArray <T>, index, value) : T 

تحدث تقريبًا ، هذه العملية ينفذ: index + = value؛

مشكلة مع القيم الممزقة.

تأثير مشكلة أخرى مع الذاكرة المشتركة هو القيم الممزقة (البيانات المهملة): عند القراءة ، يمكنك رؤية قيمة متوسطة - لا القيمة قبل كتابة القيمة الجديدة على الذاكرة أو القيمة الجديدة.

ينص المقطع "قراءة خالية من المسيل للدموع" في المواصفات على عدم وجود ثغرات إذا وفقط إذا:

  • تحدث كل من القراءة والكتابة من خلال Typed Arrays (وليس DataViews).
  • يتم محاذاة كلا الصفيفين المكتتبين مع المخازن المؤقتة للصفيف المشترك الخاص بهما: SharedArray.byteOffset٪ sharedArray.BYTES_PER_ELEMENT === 0
  • كل الصفائف المكتوبة لها نفس عدد البايتات لكل عنصر.

بمعنى آخر ، تمثل القيم الممزقة مشكلة عند الوصول إلى نفس المخزن المؤقت للصفيف المشترك عبر:

  • واحد أو أكثر من DateViews ؛
  • هناك صفيف واحد أو أكثر غير محاذاة مكتوبة ؛
  • صفائف مكتوبة بأحجام مختلفة من العناصر ؛

لتجنب وجود فجوة في القيم في هذه الحالات ، استخدم Atomics أو المزامنة.

مخازن صفيف مشتركة في الاستخدامات


مخازن صفيف مشتركة ودلالات جافا سكريبت لتنفيذ وظيفة معلقة. تحتوي JavaScript على دلالات تنفيذ ما قبل "ما قبل الإكمال": يمكن أن تتوقع كل وظيفة أنه لن يتم مقاطعتها بواسطة مؤشر ترابط آخر حتى يتم إكمالها. وظائف تصبح المعاملات ويمكن تنفيذ خوارزميات كاملة ، في حين لا أحد يرى البيانات التي يعملون في حالة وسيطة.

تقوم "مخازن صفيف مشتركة" بمقاطعة الدورة إلى الاكتمال (RTC): يمكن تغيير البيانات التي تعمل عليها الوظيفة من خلال مؤشر ترابط آخر أثناء تنفيذ الوظيفة. ومع ذلك ، تتحكم التعليمة البرمجية تمامًا في ما إذا كان انتهاك RTC هذا يحدث: إذا كان لا يستخدم Buff Array Buffers ، فهو آمن.

يشبه هذا تقريبًا كيف تنتهك الوظائف غير المتزامنة RTC. هناك يمكنك تمكين عملية القفل باستخدام الكلمة الرئيسية في انتظار.

تسمح مخازن صفيف مشتركة emscripten ترجمة pthreads في asm.js. نقلاً عن صفحة وثائق emscripten:

[En] [يسمح Array Buffers Buffers] لتطبيقات Emscripten بمشاركة كومة الذاكرة الرئيسية بين عمال الويب. هذا بالإضافة إلى البدائل للذرات ذات المستوى المنخفض ودعم futex يمكّن Emscripten من تنفيذ دعم لواجهة برمجة تطبيقات Pthreads (مؤشرات ترابط POSIX).

[Ru] [تسمح صفحات التخزين المؤقت المشتركة] لتطبيقات Emscripten بمشاركة مجموعة كبيرة من الذاكرة بين عمال الويب. جنبا إلى جنب مع البدائية الذرية منخفضة المستوى ودعم futex ، يمكّن Emscripten دعم واجهة برمجة تطبيقات Pthreads (مؤشرات POSIX).

بمعنى أنه يمكنك ترجمة التعليمات البرمجية C و C ++ متعددة مؤشرات الترابط في asm.js.

هناك نقاش مستمر حول أفضل طريقة لاستخدام تعدد العمليات في WebAssembly. نظرًا لأن العاملين على شبكة الإنترنت ثقيلة نسبياً ، فمن الممكن أن يقدم WebAssembly مؤشرات ترابط خفيفة. يمكنك أيضًا رؤية أن الموضوعات في طريقها إلى مستقبل WebAssembly.

تبادل البيانات بخلاف الأعداد الصحيحة


في الوقت الحالي ، يمكن استخدام صفيفات من الأعداد الصحيحة (حتى 32 بت). هذا يعني أن الطريقة الوحيدة لمشاركة أنواع أخرى من البيانات هي تشفيرها كأعداد صحيحة. الأدوات التي قد تساعد على ما يلي:

  • TextEncoder و TextDecoder: السابق يحول السلاسل إلى مثيلات Uint8Array ، والأخير يقوم بالعكس.
  • stringview.js: , . .
  • FlatJS: JavaScript (, ) (ArrayBuffer SharedArrayBuffer). JavaScript + FlatJS JavaScript. JavaScript (TypeScript . .) .
  • TurboScript: JavaScript- . asm.js WebAssembly.

, , — — . , .

, Shared Array?

. ( " A Taste of JavaScript's New Parallel Primitives ”», , web workers. 4 web workers , , , , 6,9 (1 web worker) 25,4 (4 web workers). web workers , .

, , .

Shared Array Buffers :


JavaScript, :


راجع كائن Atomics في المواصفات الرسمية ، وكذلك في مستندات ويب MDN .

9. وظائف المتزامن


إنشاء وظيفة Async باستخدام مُنشئ AsyncFunction


ينشئ مُنشئ AsyncFunction كائن دالة متزامن جديد. في JavaScript ، أي وظيفة غير متزامنة هي في الواقع كائن AsyncFunction.

لاحظ أن AsyncFunction ليس كائنًا عموميًا. يمكن الحصول عليها عن طريق تنفيذ التعليمات البرمجية التالية.

 Object.getPrototypeOf(async function(){}).constructor 

بناء الجملة

 new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody) 

arg1 ، arg2 ، ... argN - الأسماء المستخدمة بواسطة الدالة كأسماء وسيطة رسمية. يجب أن يكون كل اسم عبارة عن سلسلة تتطابق مع معرف JavaScript صالح أو قائمة بالسلاسل المفصولة بفواصل ؛ على سبيل المثال ، "x" أو "theValue" أو "a، b."

functionBody - سلسلة تحتوي على تعريف دالة في شفرة مصدر JavaScript.

سيتم تحليل كائنات دالة Async التي تم إنشاؤها بواسطة مُنشئ AsyncFunction فور إنشاء الوظيفة. هذا أقل فعالية من التصريح عن وظيفة غير متزامنة باستخدام تعبير وظيفة غير متزامن واستدعائها داخل الكود ، حيث يتم تحليل هذه الوظائف مع باقي الكود.

يتم التعامل مع جميع الوسائط التي تم تمريرها إلى الوظيفة كأسماء معرفات المعلمات في الوظيفة التي تم إنشاؤها بالترتيب الذي تم تمريرها به.

استدعاء مُنشئ AsyncFunction كدالة (بدون استخدام عامل التشغيل الجديد) له نفس التأثير مثل استدعاءه كمنشئ.

لا تعمل وظائف Async التي تم إنشاؤها باستخدام مُنشئ AsyncFunction على ماس كهربائى على السياقات التي تنشئها ؛ يتم إنشاؤها دائما في النطاق العالمي. عند البدء ، سيكون بإمكانهم الوصول إلى المتغيرات المحلية والمتغيرات العامة الخاصة بهم فقط ، ولكن ليس لديهم إمكانية الوصول إلى النطاقات التي تم استدعاء مُنشئ AsyncFunction فيها. هذا يختلف عن استخدام eval مع التعليمات البرمجية لوظيفة المتزامن.

مثال على إنشاء دالة غير متزامن باستخدام مُنشئ AsyncFunction

 function resolveAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x); }, 2000); }); } var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor var a = new AsyncFunction('a', 'b', 'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);'); a(10, 20).then(v => { console.log(v); //  30  4  }); 

إعلان وظيفة غير متزامن


يعرّف تعريف الدالة غير المتزامن دالة غير متزامنة تقوم بإرجاع كائن AsyncFunction. يمكنك أيضًا تحديد وظائف المزامنة باستخدام تعبير وظيفة المزامنة.

بناء الجملة

 async function name([param[, param[, ... param]]]) { // body } 

name — .
param — , .
statements — , .

async Promise. , Promise , . async , Promise (throws) .

async await, async Promise, async .

await . SyntaxError.

الغرض من وظائف المزامنة / الانتظار هو تبسيط استخدام الوعود بشكل متزامن ولعب بعض الإجراءات على مجموعة الوعود. تمامًا مثل الوعود تشبه عمليات الاسترجاعات المهيكلة ، يكون التزامن / الانتظار بمثابة مزيج من المولدات والوعود.

مثال

 function resolveAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x); }, 2000); }); } async function add1(x) { const a = await resolveAfter2Seconds(20); const b = await resolveAfter2Seconds(30); return x + a + b; } add1(10).then(v => { console.log(v); //  60  4  }); async function add2(x) { const a = resolveAfter2Seconds(20); const b = resolveAfter2Seconds(30); return x + await a + await b; } add2(10).then(v => { console.log(v); //  60  2  }); 

ما هو عدم التزامن؟


يمكنك كتابة برنامج JS الخاص بك في ملف .js واحد ، ولكن على الأرجح سيتم تقسيم الكود إلى عدة أجزاء. وسيتم تنفيذ جزء واحد فقط من الأجزاء الآن ، وسيتم تنفيذ الجزء الآخر لاحقًا. الوظيفة هي التقنية الأكثر استخدامًا لتقسيم البرنامج إلى أجزاء.

المشكلة الرئيسية لمعظم المطورين الذين يرون JS لأول مرة هي عدم فهم ما لن يحدث فورًا بعد الآن. بمعنى آخر ، المهام التي لا يمكن إكمالها الآن ، بحكم التعريف ، ستنتهي بشكل غير متزامن. ولن يكون لدينا سلوك منع البرنامج الذي نفترضه. (You-Dont-Know-JS / async & performance، Jake Archibald).

 // ajax(..)  Ajax-,   var data = ajax( "http://some.url.1" ); console.log( data );// !  `data`     Ajax- 

ما هو الخطأ هنا؟ console.log () تنفيذها قبل تلقينا البيانات من الطلب.

القرار الواضح "بالانتظار" من الآن إلى آخر هو استخدام عمليات الاسترجاعات:

 ajax( "http://some.url.1", function myCallbackFunction(data){ console.log( data ); // ,   ! } ); 

فكر في طرق مختلفة لحل تنفيذ التعليمات البرمجية المتزامنة قبل الأوان.

لدينا 3 وظائف getUser ، getPosts ، getComments.

 const { getUser, getPosts, getComments } = require('./db'); getUser(1, (error, user) => { if(error) return console.error(error); getPosts(user.id, (error, posts) => { if(error) return console.error(error); getComments(posts[0].id, (error, comment) => { if(error) return console.error(error); console.log(comments); }); }); }); 

, . Callback Hell . , () , .

Promise ( , . . .

 getUser(1) .then(user => getPosts(user,id)) .then(posts => getComments(posts[0].id)) .then(comments => console.log(comments)) .catch(error => console.error(error)); 

Promise Generators ( . , Promise, — , . try...catch. — Promise , . , co . .

 co(function* () { try { let user = yield getUser(1); let posts = yield getPosts(user.id); let comments = yield getComments(posts[0].id); console.log(comments); } catch (error) { console.log(error); } }); function co(generator) { const iterator = generator(); return new Promise((resolve, reject) => { function run(prev) { const { value, done } = iterator.next(prev); if (done) resolve(value); else if (value instanceof Promise) value.then(run, reject); else run(value); } run(); }); } 

كل من أساليب العمل مع التعليمات البرمجية غير المتزامنة لها مزايا وعيوب.
وظائف رد الاتصال (وظائف Calback) - سهلة الاستخدام ، ولكن مع زيادة الوظائف المتداخلة ، تبدأ قابلية القراءة في التضاؤل.

الوعود (الوعود) - أنيقة ومريحة ، ولكن من الصعب على المبتدئين أن يفهموا.

Generators (Generators) - تسمح لك بكتابة التعليمات البرمجية غير المتزامنة بشكل متزامن ، لكنها تتطلب وظيفة منفصلة ، وآلية تشغيل المولدات معقدة للغاية.

تم إنشاء وظائف غير متزامنة على أساس الوعود والمولدات ، وذلك لجعل العمل مع رمز غير متزامن بسيط ومفهوم.

لفهم ما هي الوظائف غير المتزامنة ، خذ بعين الاعتبار المثال التالي:

 function getUser(id) { return { id: 1 }; } let user = getUser(1); console.log(user); // { id: 1 } 

الآن إذا جعلت الوظيفة غير متزامنة (إضافة الكلمة الأساسية غير المتزامنة) ، فسوف تُرجع الدالة وعدًا يحتوي على كائن به خاصية المعرّف.

 async function getUser(id) { return { id: 1 }; } let user = getUser(1); console.log(user); // Promise { {id: 1} } 

وبالتالي ، يمكننا القول أن أي دالة غير متزامنة تقوم بإرجاع Promis (أو بالأحرى يلتف في Promis القيمة التي يجب أن تُرجع). إذا كانت القيمة التي يتم إرجاعها إلى الوظيفة غير المتزامنة تعد بالفعل ، فلن يتم قلبها مرة أخرى.

للحصول على القيمة من الوعد ، يمكننا استخدام الأسلوب then ().

 async function getUser(id) { return { id: 1 }; } getUser(1) .then(user => console.log(user)); // { id: 1 } 

أو يمكننا استخدام الكلمة الرئيسية التي تنتظر الانتظار والتي سيتم مناقشتها لاحقًا.

دعنا نرجع إلى المثال الأول (فقط هذه المرة سنستخدم الوظيفة الحقيقية لإرسال طلب HTTP.

 fetch(`https://jsonplaceholder.typicode.com/users/1`) .then(data => data.json()) .then(data => console.log(data)); 

هذا هو ما يبدو عليه الرمز غير المتزامن باستخدام Promise.
لكن يمكننا كتابة التعليمات البرمجية غير المتزامنة على أنها متزامنة إذا استخدمنا وظائف غير متزامنة.

 async function sendRequest() { let response= await fetch(`https://jsonplaceholder.typicode.com/users/1`); return response.json(); } async function main() { var a = await sendRequest(); console.log(a); } main(); 

الشيء الوحيد الذي لا يعجبني هو أن عامل التشغيل غير المتزامن لا يمكن استخدامه إلا في وظائف غير متزامنة. خلاف ذلك ، لن أحتاج إلى استخدام الوظيفة الرئيسية (). بالطبع ، يمكنك أيضًا استخدام الأسلوب then () ، لكن بعد ذلك لن يظهر الرمز غير متزامن.

 async function sendRequest() { let response= await fetch(`https://jsonplaceholder.typicode.com/users/1`); return response.json(); } sendRequest() .then((data) => console.log(data)); 

خلاصة القول هي أننا لا نستخدم وظائف رد الاتصال للحصول على البيانات من fetch (). بدلاً من ذلك ، نستخدم الكلمة المفتاحية التي تنتظر ، كما هي ، وقت التشغيل: انتظر حتى تقوم دالة fetch () بتنفيذ وكتابة النتيجة لمتغير الاستجابة. وباستخدام وظيفة رد الاتصال ، نقول: انتظر تنفيذ دالة fetch () واستدعاء وظيفة رد الاتصال لمعالجة البيانات.

هنا هو الفرق الواضح بين استخدام وظيفة وعد وغير متزامن

 //  Promise function sendRequest() { return fetch(`https://jsonplaceholder.typicode.com/users/1`) .then(data => data.json()); } //  async function async function sendRequest() { let response = await fetch(`https://jsonplaceholder.typicode.com/users/1`); return response.json(); } 

لا يمكن استخدام عامل انتظار الانتظار إلا في مجموعة الوظائف غير المتزامنة ، ويمكن استخدام الإجراء الخاص به في أي وظيفة ترجع الوعد.

لمعالجة الاستثناءات في الوظائف غير المتزامنة ، من المعتاد استخدام إنشاء try ... catch.

 async function sendRequest() { let response = await fetch(`https://jsonplaceholder.typicode.com/users/1`); try { throw new Error("Unexpected error"); return response.json(); } catch(error) { console.log(error); // Error: Unexpected error at sendRequest } } 

وأخيرا ...

  //    async; await; async; await; async; await; async; await; In the System(); The function.sleep()s tonight~ 

راجع تعريفات وظيفة Async في المواصفات الرسمية ، وكذلك في مستندات ويب MDN .

Source: https://habr.com/ru/post/ar475074/


All Articles