javascript - اغنية - promise معنى




استخدام فوريش() مع وعود في حين الوصول الوعد السابق النتائج في. ثين() سلسلة؟ (3)

لدي الوظائف التالية مع وعود:

const ajaxRequest = (url) => {
  return new Promise(function(resolve, reject) {
    axios.get(url)
      .then((response) => {
        //console.log(response);
        resolve(response);
      })
      .catch((error) => {
        //console.log(error);
        reject();
      });
  });
}


const xmlParser = (xml) => {
  let { data } = xml;
  return new Promise(function(resolve, reject) {
    let parser = new DOMParser();
    let xmlDoc = parser.parseFromString(data,"text/xml");

    if (xmlDoc.getElementsByTagName("AdTitle").length > 0) {
      let string = xmlDoc.getElementsByTagName("AdTitle")[0].childNodes[0].nodeValue;
      resolve(string);
    } else {
      reject();
    }
  });
}

أحاول تطبيق هذه الوظائف لكل كائن في مجموعة من جسون:

const array = [{"id": 1, "url": "www.link1.com"}, {"id": 1, "url": "www.link2.com"}]

توصلت إلى الحل التالي:

function example() {
    _.forEach(array, function(value) {
        ajaxRequest(value.url)
            .then(response => {
                xmlParser(response)
            .catch(err => {
                console.log(err);
            });
        });
    }
 }

كنت أتساءل عما إذا كان هذا الحل مقبولا فيما يتعلق بأمرين:

  1. هل من الممارسة الجيدة التقدم بطلب للحصول على () على الوعود في المسألة التالية.

  2. هل هناك أي طرق أفضل لتمرير نتائج الوعد السابقة كمعلمة في سلسلة ()؟ (أنا تمرير response المعلمة).


هل هناك أي طرق أفضل لتمرير نتائج الوعد السابقة كمعلمة في سلسلة ()؟

في الواقع، يمكنك سلسلة وحل الوعود في أي أمر وأي مكان من التعليمات البرمجية. قاعدة عامة واحدة - أي وعد بالسلاسل مع then أو فرع catch هو وعد جديد فقط، والتي ينبغي أن تكون بالسلاسل في وقت لاحق.

ولكن لا توجد قيود. مع استخدام الحلقات، والحل الأكثر شيوعا هو reduce الجانب الأيسر فولدل، ولكن يمكنك أيضا استخدام بسيطة let -Variable مع إعادة تعيين مع وعد جديد.

على سبيل المثال، يمكنك حتى تصميم تأخر سلسلة وعود:

function delayedChain() {
  let resolver = null
  let flow = new Promise(resolve => (resolver = resolve));
  for(let i=0; i<100500; i++) {
    flow = flow.then(() => {
      // some loop action
    })
  }

  return () => {
    resolver();
    return flow;
  }
}

(delayedChain())().then((result) => {
  console.log(result)
})

المشكلة الوحيدة مع التعليمات البرمجية التي قدمتها هو أن يتم فقدان نتيجة زملبارزر، فورش حلقة فقط يتكرر ولكن لا تخزين النتائج. للحفاظ على النتائج سوف تحتاج إلى استخدام Array.map التي سوف تحصل على وعد ونتيجة لذلك، ومن ثم Promise.all إلى الانتظار والحصول على جميع النتائج في صفيف.

أقترح استخدام غير متزامن / تنتظر من ES2017 الذي يبسط التعامل مع الوعود. منذ رمز قدمت بالفعل باستخدام وظائف السهم، الأمر الذي يتطلب تكبيل لمتصفحات كبار السن التوافق، يمكنك إضافة المساعد المساعد لدعم ES2017.

في هذه الحالة سيكون الرمز الخاص بك كما يلي:

function example() {
  return Promise.all([
    array.map(async (value) => {
      try {
        const response = await ajaxRequest(value.url);
        return xmlParser(response);
      } catch(err) {
        console.error(err);
      }
    })
  ])
}

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

async function example(processResult) {
  for(value of array) {
    let result;
    try {
      // here result has value from previous parsed ajaxRequest.
      const response = await ajaxRequest(value.url);
      result = await xmlParser(response);
      await processResult(result);
    } catch(err) {
      console.error(err);
    }
  }
}

يمكنك استخدام .reduce() للوصول إلى Promise السابق.

function example() {
    return array.reduce((promise, value) =>
       // `prev` is either initial `Promise` value or previous `Promise` value
       promise.then(prev => 
         ajaxRequest(value.url).then(response => xmlParser(response))
       )
    , Promise.resolve())
 }
 // though note, no value is passed to `reject()` at `Promise` constructor calls
 example().catch(err => console.log(err)); 

ملاحظة، منشئ Promise ليس من الضروري في وظيفة ajaxRequest .

const ajaxRequest = (url) => 
    axios.get(url)
      .then((response) => {
        //console.log(response);
        return response;
      })
      .catch((error) => {
        //console.log(error);
      });




es6-promise