वादा श्रृंखला पर सेटटाइमआउट का उपयोग करना


115

यहाँ मैं अपने सिर को वादों के इर्द-गिर्द लपेटने की कोशिश कर रहा हूँ। पहले अनुरोध पर मैंने लिंक्स का एक सेट प्राप्त किया। इस पर setTimeout। लेकिन यह मुझे निम्नलिखित JSON त्रुटि देता है ( without setTimeout() it works just fine)

SyntaxError: JSON.parse: JSON डेटा के लाइन 1 कॉलम 1 पर अप्रत्याशित चरित्र

मैं जानना चाहूंगा कि यह विफल क्यों है?

let globalObj={};
function getLinks(url){
    return new Promise(function(resolve,reject){

       let http = new XMLHttpRequest();
       http.onreadystatechange = function(){
            if(http.readyState == 4){
              if(http.status == 200){
                resolve(http.response);
              }else{
                reject(new Error());
              }
            }           
       }
       http.open("GET",url,true);
       http.send();
    });
}

getLinks('links.txt').then(function(links){
    let all_links = (JSON.parse(links));
    globalObj=all_links;

    return getLinks(globalObj["one"]+".txt");

}).then(function(topic){


    writeToBody(topic);
    setTimeout(function(){
         return getLinks(globalObj["two"]+".txt"); // without setTimeout it works fine 
         },1000);
});

1
ध्यान दें कि returnफ़ंक्शन विशिष्ट है, और केवल पैरेंट फ़ंक्शन पर लौटता है, और यह कि आप एक async विधि से नहीं लौट सकते।
एडेनो

2
ध्यान दें कि इस कोड को संरचना करने के लिए बहुत से बेहतर तरीके उपयोग किए जा सकते हैं globalObj
Bergi

कहां JSON.parseफेंकता है? मुझे यह विश्वास करना मुश्किल है कि क्या setTimeoutएक thenकॉलबैक में है, पिछले thenकॉलबैक में कॉल को प्रभावित करता है या नहीं ।
बरगी

जवाबों:


191

वादे की श्रृंखला को जारी रखने के लिए, आपने setTimeout()जिस तरह से किया था उसका उपयोग नहीं कर सकते क्योंकि आप .then()हैंडलर से एक वादा वापस नहीं कर रहे हैं - आप इसे setTimeout()कॉलबैक से वापस कर रहे हैं जो आपको अच्छा नहीं करता है।

इसके बजाय, आप इस तरह से एक साधारण सा विलंब कार्य कर सकते हैं:

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

और, फिर इसे इस तरह उपयोग करें:

getLinks('links.txt').then(function(links){
    let all_links = (JSON.parse(links));
    globalObj=all_links;

    return getLinks(globalObj["one"]+".txt");

}).then(function(topic){
    writeToBody(topic);
    // return a promise here that will be chained to prior promise
    return delay(1000).then(function() {
        return getLinks(globalObj["two"]+".txt");
    });
});

यहां आप .then()हैंडलर से एक वादा वापस कर रहे हैं और इस प्रकार इसे उचित रूप से जंजीर बनाया गया है।


आप प्रॉमिस ऑब्जेक्ट में एक देरी विधि भी जोड़ सकते हैं और फिर .delay(x)इस तरह सीधे अपने वादों पर एक विधि का उपयोग कर सकते हैं:

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

Promise.prototype.delay = function(t) {
    return this.then(function(v) {
        return delay(t, v);
    });
}


Promise.resolve("hello").delay(500).then(function(v) {
    console.log(v);
});

या, ब्लूबर्ड वादा पुस्तकालय का उपयोग करें जिसमें पहले से ही .delay()निर्मित विधि है।


1
समाधान फ़ंक्शन तब () .. के अंदर फ़ंक्शन होता है, इसलिए सेटटाइमआउट (रिज़ॉल्यूशन, टी) का अर्थ सेटटाइमआउट (फ़ंक्शन () {वापसी ....}, टी) है ... क्या यह काम नहीं करेगा?
अल-ज़मी

2
@ AL-zami - delay()एक वादा लौटाता है जिसे बाद में हल किया जाएगा setTimeout()
jfriend00

मैं आसानी से एक वादा में देरी करने के लिए setTimeout के लिए एक वादा आवरण बनाया है। github.com/zengfenfei/delay
केविन

4
@pdem - vएक वैकल्पिक मूल्य है जिसे आप हल करने के लिए विलंब वादे को पसंद करेंगे और इस प्रकार वादा श्रृंखला को समाप्त करेंगे। resolve.bind(null, v)के स्थान पर है function() {resolve(v);} या तो काम करेंगे।
मृगशीर्ष

बहुत बहुत धन्यवाद ... प्रोटोटाइप देरी ने काम किया, लेकिन फ़ंक्शन नहीं >>> यह कथन। t अपरिभाषित था।
ईसाई मैथ्यू

75
.then(() => new Promise((resolve) => setTimeout(resolve, 15000)))

अपडेट करें:

जब मुझे async फ़ंक्शन में नींद की आवश्यकता होती है, तो मैं फेंक देता हूं

await new Promise(resolve => setTimeout(resolve, 1000))

तुम सिर्फ एक async समारोह के भीतर सो नहीं सकता ऐसा? नई प्रतिज्ञा का इंतजार करें (संकल्प => सेटटाइमआउट (संकल्प, 1000));
एंथनी मून बीम टॉयलेट

@AnthonyMoonBeamToorie तय, ty
इगोर कोर्साकोव

52

उत्तर का छोटा ES6 संस्करण:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

और फिर आप कर सकते हैं:

delay(3000).then(() => console.log('Hello'));

और यदि आपको rejectविकल्प की आवश्यकता है , उदाहरण के लिए अनुगमन सत्यापन के लिए, तोconst delay = ms => new Promise((resolve, reject) => setTimeout(resolve, ms))
डेविड थॉमस

10

यदि आप एक के अंदर कर रहे हैं तो फिर () ब्लॉक और आप एक पर अमल करना चाहते हैं setTimeout ()

            .then(() => {
                console.log('wait for 10 seconds . . . . ');
                return new Promise(function(resolve, reject) { 
                    setTimeout(() => {
                        console.log('10 seconds Timer expired!!!');
                        resolve();
                    }, 10000)
                });
            })
            .then(() => {
                console.log('promise resolved!!!');

            })

आउटपुट नीचे दिखाया जाएगा

wait for 10 seconds . . . .
10 seconds Timer expired!!!
promise resolved!!!

हैप्पी कोडिंग!


-1

नोड.जेएस में आप निम्न कार्य भी कर सकते हैं:

const { promisify } = require('util')
const delay = promisify(setTimeout)

delay(1000).then(() => console.log('hello'))

मैंने इसे आज़माया और विलंबित फ़ंक्शन के तहत, अमान्य तर्कों की अपेक्षा की, 0 की उम्मीद की।
एलेक्स रिंडोन

मैं यह पुष्टि कर सकता हूं कि यह नोड में काम करता है। 8, 10, 12, 13. यह सुनिश्चित न करें कि आप अपना कोड कैसे चला रहे हैं, लेकिन मैं केवल यह मान सकता हूं कि utilगलत तरीके से पॉलीफ़िल किया जा रहा है। क्या आप एक बंडल या कुछ का उपयोग कर रहे हैं?
जन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.