it-swarm.dev

كيفية التحقق ما إذا كان Angular وعد $ ف حل

أدرك أنه عادةً ما يتم إرفاق رمز الاستمرار مع استدعاء then() وسلوك السلسلة عند استخدام الوعود.

ومع ذلك ، أريد بدء مكالمة غير متزامنة ملفوفة بالوعود ، ثم إطلاق منفصلة $timeout() لمدة 3 ثوان حتى أتمكن من اتخاذ إجراء واجهة المستخدم ، فقط إذا لم يكتمل الوعد الأصلي بعد. (أتوقع أن يحدث هذا فقط على الاتصالات البطيئة والأجهزة المحمولة على 3G ، وما إلى ذلك)

إذا أعطيت وعدًا ، هل يمكنني التحقق من اكتماله أم لا دون حظر أو انتظار؟

82
blaster

أعتقد أنه تمت إضافة هذا في إصدار حديث من Angular ، لكن يبدو أن هناك كائنًا على شكل $$ على الوعد:

 var deferred = $q.defer();
 console.log(deferred.promise.$$state.status); // 0
 deferred.resolve();
 console.log(deferred.promise.$$state.status); //1 

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

46
parliament

أعتقد أن أفضل خيار لديك هو (دون تعديل المصدر Angular وإرسال طلب سحب) هو الاحتفاظ بالعلم المحلي إذا تم حل الوعد. أعد تعيينه في كل مرة تقوم فيها بإعداد الوعد الذي تهتم به ووضع علامة عليه كاملاً في then() للوعد الأصلي. في $timeoutthen() تحقق من العلم لمعرفة ما إذا كان الوعد الأصلي قد حل أم لا.

شيء من هذا القبيل:

var promiseCompleted = false;
promise.then(function(){promiseCompleted=true;})
$timeout(...).then(function(){if(!promiseCompleted)doStuff()})

يتضمن تطبيق Kris Kowal طرقًا أخرى للتحقق من حالة الوعد ، لكن يبدو أن تطبيق Angular لـ $q للأسف لا يتضمن هذه.

36
shaunhusain

لا يبدو ذلك ممكنًا ، كما ذكرت @ شونهوسين بالفعل. ولكن ربما ليس من الضروري:

// shows stuff from 3s ahead to promise completetion, 
// or does and undoes it in one step if promise completes before
$q.all(promise, $timeout(doStuff, 3000)).then(undoStuff);

أو ربما أفضل:

var tooSlow = $timeout(doStuff, 3000);
promise.always(tooSlow.cancel);
8
Bergi

لقد واجهت مشكلة مماثلة حيث أحتاج إلى التحقق مما إذا كان الوعد قد عاد. نظرًا لأن وظيفة $watch الخاصة بـ AngularJS ستسجل تغييرًا أثناء تقديم الصفحة حتى لو لم يتم تحديد كل من القيم الجديدة والقديمة ، يتعين علي التحقق لمعرفة ما إذا كان هناك أي بيانات تستحق التخزين في نموذجي الخارجي.

إنه بالتأكيد اختراق لكني أفعل هذا:

$scope.$watch('userSelection', function() {
  if(promiseObject.hasOwnProperty("$$v"){
    userExportableState.selection = $scope.userSelection;
  }
};

أعلم أن $$v هو متغير داخلي تستخدمه AngularJS ، لكنه كان موثوقًا تمامًا كمؤشر على الوعد الذي قطعناه. من يعرف ماذا سيحدث عند الترقية إلى AngularJS 1.2: -/لا أرى أي ذكر للتحسينات التي تم إجراؤها على $q في مستندات 1.2 ولكن ربما شخص ما سيكتب خدمة بديلة مع ميزة أفضل معيّنة أقرب إلى Q.

1
PatchCR

لا أعلم السيناريو بالضبط ، لكن من المعتاد وضع مهلة في الحال بعد إجراء المكالمة غير المتزامنة (وتوليد الوعد).

توفير عبارة setTimeout() في نفس مؤشر ترابط الأحداث مثل المكالمة غير المتزامنة ، فلا داعي للقلق بشأن إمكانية حدوث تأثير سباق. نظرًا لأن javascript مفردة الترابط بشكل صارم ، فإن عمليات الاسترجاع .then() للوعد مضمونة لإطلاقها في سلسلة أحداث لاحقة.

0
Beetroot-Beetroot